1 /*************************************************** 2 题目: Popular Cows(poj 2186) 3 链接: http://poj.org/problem?id=2186 4 算法: 强连通缩点 5 思想: 首先在一个连通分量上的点性质都是一样的, 6 所以就找出所有连通图并缩点,得到有向无 7 环图,已知要是最受欢迎就必须是出度为0点, 8 并且还是唯一的一个。 9 ***************************************************/ 10 #include<iostream> 11 #include<cstdio> 12 #include<cstring> 13 #include<algorithm> 14 #include<vector> 15 #include<stack> 16 using namespace std; 17 18 const int mx=10005; 19 vector<int>g[mx]; 20 int n,m; 21 int vs[mx]; 22 int dfs_cut=0,gcc_cut=0; 23 int dfn[mx],low[mx]; 24 int scc[mx],out[mx]; 25 int ans[mx]; 26 stack<int>s; 27 28 void dfs(int u) 29 { 30 dfn[u]=low[u]=++dfs_cut; 31 vs[u]=1; 32 s.push(u); 33 for (int i=0;i<g[u].size();i++) 34 { 35 int v=g[u][i]; 36 if(!vs[v]) 37 { 38 dfs(v); 39 low[u]=min(low[v],low[u]); 40 } 41 else if (!scc[v]) low[u]=min(low[u],dfn[v]); 42 } 43 if (low[u]==dfn[u]) 44 { 45 gcc_cut++; 46 int cut=0; 47 while (1) 48 { 49 int v=s.top(); 50 cut++; 51 s.pop(); 52 scc[v]=gcc_cut; 53 if (u==v) break; 54 55 } 56 ans[gcc_cut]=cut; 57 } 58 } 59 60 int main() 61 { 62 scanf("%d%d",&n,&m); 63 int u,v; 64 while (m--) 65 { 66 scanf("%d%d",&u,&v); 67 g[u].push_back(v); 68 } 69 for (int i=1;i<=n;i++) 70 { 71 if (!vs[i]) dfs(i); 72 } 73 74 for (u=1;u<=n;u++) 75 { 76 for (int i=0;i<g[u].size();i++) 77 { 78 v=g[u][i]; 79 if (scc[u]==scc[v]) continue; 80 out[scc[u]]=1; 81 } 82 } 83 int flag=0,ans1; 84 for (int i=1;i<=gcc_cut;i++) 85 { 86 if (!out[i]) 87 { 88 flag++; 89 ans1=ans[i]; 90 } 91 } 92 if (flag==1) printf("%d\n",ans1); 93 else printf("0\n"); 94 95 }