题目大意:

给定一系列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 }

 

 posted on 2014-08-08 20:43  Love风吟  阅读(218)  评论(0编辑  收藏  举报