题目大意
n(1<=n<=10000) 头牛,有 m(1<=m<=50000) 个推举关系。推举关系具有传递性,即 A 推举 B, B 推举 C,那么 A 也推举 C
问你,能够得到所有牛推举的牛有多少头?
做法分析
求强连通分量缩点后反向建图
然后判断图中是否有且仅有一个点的入度为 0,是的话就输出这个店包含的牛的个数,否则就输出 0
参考代码
POJ 2186
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <vector> 5 #include <stack> 6 7 using namespace std; 8 9 const int N=10006; 10 11 vector <int> arc[N]; 12 stack <int> s; 13 int dfn[N], low[N], cnt[N], id[N]; 14 int n, m, T, ind; 15 bool vs[N]; 16 17 void tarjan(int u) 18 { 19 vs[u]=1, s.push(u); 20 dfn[u]=low[u]=T++; 21 int len=(int)arc[u].size(); 22 for(int i=0; i<len; i++) 23 { 24 int v=arc[u][i]; 25 if(dfn[v]==-1) 26 { 27 tarjan(v); 28 if(low[u]>low[v]) low[u]=low[v]; 29 } 30 else if(vs[v] && dfn[v]<low[u]) low[u]=dfn[v]; 31 } 32 if(dfn[u]==low[u]) 33 { 34 for(int v; 1; ) 35 { 36 v=s.top(); 37 s.pop(), vs[v]=0; 38 cnt[ind]++, id[v]=ind; 39 if(u==v) break; 40 } 41 ind++; 42 } 43 } 44 45 int main() 46 { 47 scanf("%d%d", &n, &m); 48 for(int i=0; i<=n; i++) arc[i].clear(); 49 for(int i=0, a, b; i<m; i++) 50 { 51 scanf("%d%d", &a, &b); 52 arc[a].push_back(b); 53 } 54 for(int i=0; i<=n; i++) vs[i]=0, dfn[i]=-1, cnt[i]=0; 55 while(!s.empty()) s.pop(); 56 T=ind=0; 57 for(int i=1; i<=n; i++) if(dfn[i]==-1) tarjan(i); 58 for(int i=0; i<ind; i++) dfn[i]=0; 59 for(int i=1; i<=n; i++) 60 { 61 int len=(int)arc[i].size(), u=id[i]; 62 for(int j=0; j<len; j++) 63 { 64 int v=id[arc[i][j]]; 65 if(u!=v) dfn[u]++; 66 } 67 } 68 int ans=0, flag=0; 69 for(int i=0; i<ind; i++) 70 if(dfn[i]==0) 71 { 72 ans=cnt[i]; 73 flag++; 74 } 75 if(flag!=1) ans=0; 76 printf("%d\n", ans); 77 return 0; 78 }