POJ 2186 Popular Cows (强连通分量)

题目大意:有n个牛,已知这些牛之间的崇拜关系,崇拜关系是可以传递的,例如:a崇拜b,b崇拜c,那么a崇拜c。问有多少牛被其他所有牛崇拜?

分析:根据崇拜关系建立有向图,已知同属于一个强连通分量的牛互相崇拜,通过求强连通缩点后,若出度为0的点只有一个,那么这一群牛就被其他所有牛崇拜,否则不存在被其他所有牛崇拜的牛。

View Code
#include <stdio.h>
#include <string.h>
#define N 10001
#define M 50001
int first[N],next[M],v[M];
int rfirst[N],rnext[M],rv[M];
int n,m,e;
int vis[N],dfn[N],id[N],cnt,num[N];
int dout[N];
void init()
{
    e=0;
    memset(first,-1,sizeof(first));
    memset(rfirst,-1,sizeof(rfirst));
}
void insert(int a,int b)
{
    v[e]=b;
    next[e]=first[a];
    first[a]=e;

    rv[e]=a;
    rnext[e]=rfirst[b];
    rfirst[b]=e++;
}
void dfs(int a)
{
    int i,b;
    vis[a]=1;
    for(i=first[a];i!=-1;i=next[i])
    {
        b=v[i];
        if(!vis[b]) dfs(b);
    }
    dfn[cnt++]=a;
}
void rdfs(int a)
{
    int i,b;
    vis[a]=1;
    id[a]=cnt;
    num[cnt]++;
    for(i=rfirst[a];i!=-1;i=rnext[i])
    {
        b=rv[i];
        if(!vis[b]) rdfs(b);
    }
}
void solve()
{
    int i,j,a,b,t;
    cnt=0;
    memset(vis,0,sizeof(vis));
    for(i=1;i<=n;i++)
    {
        if(!vis[i]) dfs(i);
    }
    cnt=0;
    memset(vis,0,sizeof(vis));
    memset(num,0,sizeof(num));
    for(t=n-1;t>=0;t--)
    {
        i=dfn[t];
        if(!vis[i]) rdfs(i),cnt++;
    }
    memset(dout,0,sizeof(dout));
    for(a=1;a<=n;a++)
    {
        for(i=first[a];i!=-1;i=next[i])
        {
            b=v[i];
            if(id[a]^id[b]) dout[id[a]]++;
        }
    }
    int x=0;
    for(i=0;i<cnt;i++)
    {
        if(!dout[i])
        {
            x++;
            j=i;
        }
    }
    if(x>1) puts("0");
    else    printf("%d\n",num[j]);
}
int main()
{
    int a,b;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        while(m--)
        {
            scanf("%d%d",&a,&b);
            insert(a,b);
        }
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/algorithms/p/2610646.html