HAOI2006 受欢迎的牛 缩点

不难分析出我们就是要求是否有唯一一个出度为0的强连通分量。
Code:

#include<cstdio>
#include<stack>
#include<algorithm>
using namespace std;
const int N=50000+3;
stack<int>S;
int head[N],to[N<<1],nex[N<<1], cnt;
int pre[N],low[N],vis[N], sig, scc;
int idx[N],siz[N];
int du[N];
void add_edge(int u,int v)
{
    nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v;
}
void tarjan(int u)
{
    S.push(u);
    pre[u]=low[u]=++scc;
    vis[u]=1;
    for(int v=head[u];v;v=nex[v])
    {
        if(!vis[to[v]]){
            tarjan(to[v]);low[u]=min(low[u],low[to[v]]);
        }
        else if(vis[to[v]]==1)low[u]=min(low[u],pre[to[v]]);
    }
    if(pre[u]==low[u])
    {
        ++sig;
        for(;;)
        {
            int a=S.top();S.pop();
            vis[a]=-1,idx[a]=sig,siz[sig]+=1;
            if(a==u)break;
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add_edge(a,b);
    }
    for(int i=1;i<=n;++i)
        if(!vis[i])tarjan(i);
    int cc=0,ans=0;
    for(int i=1;i<=n;++i)
        for(int v=head[i];v;v=nex[v])
            if(idx[i]!=idx[to[v]])du[idx[i]]=1;
    for(int i=1;i<=sig;++i)
        if(!du[i])cc+=1,ans=siz[i];
    if(cc>1)printf("0");
    else printf("%d",ans);
    return 0;
}

  

 
原文地址:https://www.cnblogs.com/guangheli/p/9845172.html