首页 > 代码库 > POJ 2186

POJ 2186

题目大意:

给定一系列A->B的关系,说明A崇拜B,若A崇拜B,B崇拜C,那么A崇拜C,问存在多少头牛被其他所有牛都崇拜

 

一道强连通分量的水题,将一个强连通分量的牛看做一个整体,记录每个强连通分量中牛的个数

其实我们仔细想想,当把所有强连通分量都缩点后,例如强连通分量为3,那么剩下来的有向边必然小于3,否则将会导致中间某处又生成环形成强连通分量

所以如果存在出度为0的连通分量2个及两个以上,说明这2点是不能互达的,说明没有牛被崇拜

同样道理,若只有一个,那么找到那个连通分量中牛的头数,这就是解

 

总代码如下:

 1 #include <cstdio> 2 #include <cstring> 3 #include <stack> 4 #include <algorithm> 5 using namespace std; 6 #define N 10005 7 struct Path{ 8     int y,next; 9 }path[50010];10 int tmpdfn,outdegree[N],cnt[N],scc[N],k,scc_cnt,first[N],dfn[N],low[N];11 stack<int> s;12 void add(int x,int y)13 {14     path[k].y=y,path[k].next=first[x];15     first[x]=k;16     k++;17 }18 void dfs(int u,int fa)19 {20     dfn[u]=low[u]=++tmpdfn;21     s.push(u);22     for(int i=first[u];i!=-1;i=path[i].next){23         int v=path[i].y;24         if(!dfn[v]){25             dfs(v,u);26             low[u]=min(low[v],low[u]);27         }28         else if(!scc[v]) low[u]=min(low[u],dfn[v]);29     }30     if(dfn[u]==low[u]){31         scc_cnt++;32         int m=0;33         for(;;){34             int t=s.top();s.pop();35             scc[t]=scc_cnt;36             m++;37             if(t==u) break;38         }39         cnt[scc_cnt]=m;40         //printf("scc: %d  %d\n",scc_cnt,m);41     }42 }43 void get_scc(int n)44 {45     for(int i=1;i<=n;i++)46         if(!dfn[i]) dfs(i,-1);47 48     for(int i=1;i<=n;i++)49         for(int j=first[i];j!=-1;j=path[j].next)50             if(scc[i]!=scc[path[j].y]){ outdegree[scc[i]]++;}51 }52 int main()53 {54     int n,m,a,b;55     scanf("%d%d",&n,&m);56     memset(dfn,0,sizeof(dfn));57     memset(first,-1,sizeof(first));58     memset(scc,0,sizeof(scc));59     memset(cnt,0,sizeof(cnt));60     memset(outdegree,0,sizeof(outdegree));61     tmpdfn=0,k=0,scc_cnt=0;62     for(int i=0;i<m;i++){63         scanf("%d%d",&a,&b);64         add(a,b);65     }66     get_scc(n);67     int t=0,p;68     for(int i=1;i<=scc_cnt;i++){69         //printf("%d\n",outdegree[i]);70         if(outdegree[i]==0) t++,p=i;71         if(t>=2) break;72     }73     if(t>=2) puts("0");74     else printf("%d\n",cnt[p]);75     return 0;76 }