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;

}

 

你可能感兴趣的:(poj)