haoi2006_受欢迎的牛_Solution
Brief Solution:
强连通tarjan+压缩点+判断是否除了一个点,其它点都有出度
Detailed Solution:
把牛看成点
若一个点b能到达点a,则b认为a受欢迎
若所有的点都能到达点a,则a被所有的牛欢迎
对于某个强连通中的点,任意两点可互达,互相受欢迎
对图求强连通,并把强连通压缩成一个点
若点a向与点a不在同一个强连通集合的点b,则点a所在的集合指向点b所在的集合(边)
若一个强连通集合的点(新图的点A)能被所有的点到达,则新图所有的点能到达点A
此时新图没有环,若一个点A能被所有的点到达,则除了该点,其它点的出度都不为0(图必有没有出度的点,因为图没有环)
则能被所有的点到达的点只有一个,否则会有环,矛盾
(在没有环的条件下,图中所有的点到汇集(到达)该点)
Code:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdbool.h> 4 #include <malloc.h> 5 #define maxn 10000 6 #define maxm 50000 7 8 struct node 9 { 10 long d; 11 struct node *next; 12 }*info[maxn+1]; 13 long x[maxm+1],y[maxm+1]; 14 long dfn[maxn+1],low[maxn+1],stack[maxn+1],num[maxn+1],ans[maxn+1],count=0,sum=0; 15 bool vis[maxn+1],vis_stack[maxn+1],next[maxn+1]; 16 17 long min(long a,long b) 18 { 19 if (a>b) 20 return b; 21 else 22 return a; 23 } 24 25 void tarjan(long d) 26 { 27 vis[d]=false; 28 count++; 29 stack[count]=d; 30 dfn[d]=count; 31 low[d]=count; 32 struct node *p; 33 long nd,pre; 34 p=info[d]; 35 while (p) 36 { 37 nd=p->d; 38 if (vis[nd]==true) 39 { 40 tarjan(nd); 41 low[d]=min(low[d],low[nd]); 42 } 43 else if (vis_stack[nd]==true) 44 low[d]=min(low[d],dfn[nd]); 45 p=p->next; 46 } 47 pre=count; 48 if (dfn[d]==low[d]) 49 { 50 sum++; 51 while (d!=stack[count]) 52 { 53 num[stack[count]]=sum; 54 vis_stack[stack[count]]=false; 55 count--; 56 } 57 num[stack[count]]=sum; 58 vis_stack[stack[count]]=false; 59 count--; 60 ans[sum]=pre-count; //count+1~pre 61 } 62 } 63 64 int main() 65 { 66 long i,n,m,d; 67 struct node *p; 68 scanf("%ld%ld",&n,&m); 69 // for (i=1;i<=n;i++) 70 // info[i]=NULL; 71 for (i=1;i<=m;i++) 72 { 73 scanf("%ld%ld",&x[i],&y[i]); 74 p=(struct node *) malloc (sizeof(struct node)); 75 p->d=y[i]; 76 p->next=info[x[i]]; 77 info[x[i]]=p; 78 } 79 for (i=1;i<=n;i++) 80 { 81 vis[i]=true; 82 vis_stack[i]=true; 83 } 84 for (i=1;i<=n;i++) 85 if (vis[i]==true) 86 tarjan(i); 87 for (i=1;i<=sum;i++) 88 next[i]=false; 89 for (i=1;i<=m;i++) 90 if (num[x[i]]!=num[y[i]]) 91 next[num[x[i]]]=true; 92 d=0; 93 for (i=1;i<=sum;i++) 94 if (next[i]==false) 95 { 96 if (d==0) 97 d=i; 98 else 99 { 100 d=-1; 101 break; 102 } 103 } 104 if (d==-1) 105 printf("0\n"); 106 else 107 printf("%ld\n",ans[d]); 108 return 0; 109 }