Network of Schools (tarjan reduction point + statistical degree)

http://poj.org/problem?id=1236


Idea: There are other ways to do the first question. That question is called burning a disc, and it is done by checking and counting the degrees. P2835 burn CD (and check the set to build one-way edge)

The idea of ​​this question: first tarjan shrinks. After shrinking the points, look at how many points with 0 in-degree are between the new images. This is the last point to be given as the starting point.

For the second question, after condensing the points, you will find that after considering several situations:

1-->2<----3

       ^

       |

       4

 2<----1------>3

           |

           V

           4

It is necessary to choose the largest in degree of 0 and out degree of 0 respectively.

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<stack>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e2+100;
typedef long long LL;
vector<LL>g[maxn];
stack<LL>s;
LL dfn[maxn],low[maxn],times=0,cnt=0,in[maxn],out[maxn];
bool inq[maxn];
LL col[maxn];///缩点
void tarjan(LL x)
{
    dfn[x]=low[x]=++times;
    s.push(x);inq[x]=true;
    for(LL i=0;i<g[x].size();i++)
    {
        LL to=g[x][i];
        if(!dfn[to])
        {
            tarjan(to);
            low[x]=min(low[x],low[to]);
        }
        else if(inq[to])
        {
            low[x]=min(low[x],dfn[to]);
        }
    }
    if(dfn[x]==low[x])
    {
        cnt++;
        LL y;
        do
        {
            y=s.top();
            inq[y]=false;
            col[y]=cnt;
            s.pop();
        }while(y!=x);
        return;
    }
}
int main(void)
{
    LL n;cin>>n;
    for(LL i=1;i<=n;i++)
    {
        LL to;
        while(cin>>to&&to!=0)
        {
            g[i].push_back(to);
        }
    }
    for(LL i=1;i<=n;i++)
    {
        if(!dfn[i]) tarjan(i);
    }
    if(cnt==1) cout<<1<<endl<<0<<endl;
    else
    {
        for(LL i=1;i<=n;i++)
        {
            for(LL j=0;j<g[i].size();j++)
            {
                if(col[i]!=col[g[i][j]]) in[col[g[i][j]]]++,out[col[i]]++;
            }
        }
        LL ans1=0;LL ans2=0;
        for(LL i=1;i<=cnt;i++)
        {
            if(in[i]==0) ans1++;
            if(out[i]==0) ans2++;
        }
        cout<<ans1<<endl<<max(ans1,ans2)<<endl;
    }
}

    

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/108885156