新注册了博客,正好刚刚开始做强连通专题,就当存个模板了
题目简述:n头奶牛,给出若干个欢迎关系a b,表示a欢迎b,欢迎关系是单向的,但是是可以传递的。另外每个奶牛都是欢迎他自己的。求出被所有的奶牛欢迎的奶牛的数目。
思路:先得出每个强连通分块的规模,再检查输入的每一条边,如果这边连着2个不同的强连通分块,那么被指向的分块才可能是答案。当答案不唯一时则说明至少有两头牛没有任何关系,这时输出0.
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 const int Max = 20009; 8 #define max(a,b) a>b?a:b 9 10 struct node{ 11 int v,next; 12 }Edge[100000]; 13 14 int k,Dindex,Stop,Bcnt; 15 int head[Max],DFN[Max],LOW[Max],instack[Max],Stap[Max],Belong[Max]; 16 int a[50009],b[50009],cnt[Max]; 17 bool ok[Max]; 18 19 void add(int u,int v){ 20 Edge[k].v = v; 21 Edge[k].next = head[u]; 22 head[u] = k++; 23 } 24 25 void tarjan(int i) 26 { 27 int j; 28 DFN[i]=LOW[i]=++Dindex; 29 instack[i]=true; 30 Stap[++Stop]=i; 31 for (int w=head[i];w!=-1;w=Edge[w].next) 32 { 33 j=Edge[w].v; 34 if (!DFN[j]) 35 { 36 tarjan(j); 37 if (LOW[j]<LOW[i]) 38 LOW[i]=LOW[j]; 39 } 40 else if (instack[j] && DFN[j]<LOW[i]) 41 LOW[i]=DFN[j]; 42 } 43 if (DFN[i]==LOW[i]) 44 { 45 Bcnt++; 46 do 47 { 48 j=Stap[Stop--]; 49 instack[j]=false; 50 Belong[j]=Bcnt; 51 } 52 while (j!=i); 53 } 54 } 55 56 int main() { 57 int n,m; 58 while(scanf("%d%d",&n,&m) == 2){ 59 memset(head,-1,sizeof(head)); 60 memset(DFN,0,sizeof(DFN)); 61 memset(instack,0,sizeof(instack)); 62 memset(LOW,0,sizeof(LOW)); 63 k = 0; 64 for(int i=0;i<m;i++){ 65 scanf("%d%d",&a[i],&b[i]); 66 add(a[i],b[i]); 67 } 68 Stop=Bcnt=Dindex=0; 69 for(int i=1;i<=n;i++){ 70 if(DFN[i] == 0) 71 tarjan(i); 72 } 73 for(int i=1;i<=n;i++) 74 cnt[Belong[i]]++; 75 76 int num = 0,ans; 77 for(int i=0;i<m;i++){ 78 if(Belong[a[i]] != Belong[b[i]]){ 79 ok[Belong[a[i]]] = true; 80 } 81 } 82 for(int i=1;i<=Bcnt;i++){ 83 if(!ok[i]){ 84 num++; 85 ans = cnt[i]; 86 } 87 } 88 if(num != 1) 89 printf("0\n"); 90 else 91 printf("%d\n",ans); 92 } 93 return 0; 94 }