有向图强连通分量-poj-2186-Popular Cows

来源:互联网 发布:网络存储软件有哪些 编辑:程序博客网 时间:2024/05/20 05:58




题意:有些牛有自己的偶像,偶像的偶像也是自己的偶像,问存在多少牛被所有牛崇拜。


题解:牛a崇拜牛b就连一条a指向b的边,然后找出所有的强连通分量(即这个分量里的每个点都可以到达分量中的任意一个点)。判断有没有出度为0的强连通分量,而且这个点只有一个,如果有,那么答案就是这个强连通分量里面点的个数。

顺便可以把这个作为强连通分量的模板。


先放一个tarjan 强连通分量模板

struct recordtime{    int index,low;}tour[SIZE_N];stack<int>sta;int vernum,edgnum,Dindex,    scc;int used[SIZE_N],instack[SIZE_N],    belong[SIZE_N],num[SIZE_M];void inittarjan(){    Dindex=0;    scc=0;    memset(used,-1,sizeof(used));    memset(instack,0,sizeof(instack));    memset(belong,0,sizeof(belong));    memset(num,0,sizeof(num));}void tarjan(int x){    int w,u;    used[x]=1;    tour[x].index=Dindex;    tour[x].low=Dindex;    Dindex++;    sta.push(x);    instack[x]=1;    for(int an=head[x];an!=-1;an=pra[an].next)    {        u=pra[an].to;        if(used[u]==-1)        {            tarjan(u);            tour[x].low=min(tour[x].low,tour[u].low);        }        else        {            //查找栈中的元素            if(instack[u]==1)                tour[x].low=min(tour[x].low,tour[u].index);        }    }    if(tour[x].low==tour[x].index)    {        scc++;        do        {            w=sta.top();            sta.pop();            instack[w]=0;            belong[w]=scc;            num[scc]++;            //printf("%d ",w);        }while(w!=x);        //printf("\n");    }}

再放一个已经ac的完整代码

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#define SIZE_N 10100#define SIZE_M 50100using namespace std;struct peck{    int to,next;}pra[SIZE_M];int e,outnum,ang;int head[SIZE_N],out[SIZE_N];void init(){    e=0;    memset(head,-1,sizeof(head));    outnum=0;    ang=0;    memset(out,0,sizeof(out));}void addedge(int x,int y){    pra[e].to=y;    pra[e].next=head[x];    head[x]=e++;}struct recordtime{    int index,low;}tour[SIZE_N];stack<int>sta;int vernum,edgnum,Dindex,    scc;int used[SIZE_N],instack[SIZE_N],    belong[SIZE_N],num[SIZE_M];void inittarjan(){    Dindex=0;    scc=0;    memset(used,-1,sizeof(used));    memset(instack,0,sizeof(instack));    memset(belong,0,sizeof(belong));    memset(num,0,sizeof(num));}void tarjan(int x){    int w,u;    used[x]=1;    tour[x].index=Dindex;    tour[x].low=Dindex;    Dindex++;    sta.push(x);    instack[x]=1;    for(int an=head[x];an!=-1;an=pra[an].next)    {        u=pra[an].to;        if(used[u]==-1)        {            tarjan(u);            tour[x].low=min(tour[x].low,tour[u].low);        }        else        {            //查找栈中的元素            if(instack[u]==1)                tour[x].low=min(tour[x].low,tour[u].index);        }    }    if(tour[x].low==tour[x].index)    {        scc++;        do        {            w=sta.top();            sta.pop();            instack[w]=0;            belong[w]=scc;            num[scc]++;            //printf("%d ",w);        }while(w!=x);        //printf("\n");    }}void pri(){    for(int i=1;i<=vernum;i++)    {        printf("the %d th     ",i);        for(int an=head[i];an!=-1;an=pra[an].next)            printf("%d ",pra[an].to);        printf("\n");    }}int main(){    int compact,burgeon;    //存图    while(scanf("%d %d",&vernum,&edgnum)!=EOF)    {        init();        inittarjan();        for (int i = 1;i<=edgnum;i++)        {            scanf("%d %d",&compact,&burgeon);            addedge(compact,burgeon);        }        //pri();        for (int i = 1;i<=vernum;i++)        {            if(used[i]==-1)                tarjan(i);        }        for (int i = 1;i<=vernum;i++)        {            for(int an=head[i];an!=-1;an=pra[an].next)            {                int u=pra[an].to;                int verbe=belong[i];                int tobe=belong[u];                if(verbe!=tobe){                    out[verbe]=1;//出度不为0                    //printf("dengyuyi%d\n",u);                }            }        }        for (int i = 1;i<=scc;i++)//这里i是<=强连通分量的组数        {            //printf("out[%d]=%d\n",i,out[i]);            if(out[i]==0)            {                outnum++;                ang=i;            }//printf("%d\n",ang);        }        if(outnum!=1)//如果出度不为0的强连通分量有两个  那说明并不是被所有牛崇拜            num[ang]=0;        printf("%d\n",num[ang]);    }    return 0;}


0 0