BZOJ-1051: [HAOI2006]受欢迎的牛(tarjan求强连通分量)
1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4194 Solved: 2247
[Submit][Status][Discuss]
Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
1 2
2 1
2 3
Sample Output
1
HINT
100%的数据N<=10000,M<=50000
Source
只要找到缩点后的图中无出度的点的个数,设为count, 若 count > 1 , 则必无满足条件的点,因为一个出度为零的点无法到达另一个出度为零的点;若count = 1 , 则该点所对应的强联通分量的点的个数即为答案。
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <cstdlib> 5 #include <iostream> 6 #include "algorithm" 7 using namespace std; 8 typedef long long LL; 9 const int MAX1=10005; 10 const int MAX2=50005; 11 int n,m; 12 int tot,c; 13 int dfn[MAX1],low[MAX1],ins[MAX1]; 14 int head[MAX1],adj[MAX2],next[MAX2]; 15 bool t[MAX1]; 16 int sta[MAX1],gid[MAX1],con[MAX1]; 17 int out,tx; 18 int ans; 19 void addedge(int u,int v){ 20 tot++; 21 adj[tot]=v; 22 next[tot]=head[u]; 23 head[u]=tot; 24 } 25 void init(){ 26 int i,j; 27 int u,v; 28 scanf("%d%d",&n,&m); 29 memset(gid,0,sizeof(gid)); 30 memset(next,0,sizeof(next)); 31 memset(ins,0,sizeof(ins)); 32 for (i=1;i<=m;i++) 33 {scanf("%d%d",&u,&v); 34 addedge(u,v); 35 } 36 memset(t,false,sizeof(t)); 37 tx=out=ans=c=sta[0]=0; 38 } 39 int dfs(int x){ 40 int i,j; 41 t[x]=true; 42 sta[++sta[0]]=x;ins[x]=1; 43 dfn[x]=++c;low[x]=dfn[x]; 44 for (i=head[x];i;i=next[i]) 45 if (t[adj[i]]) 46 {if (ins[adj[i]]==1) 47 low[x]=min(low[x],dfn[adj[i]]);} 48 else 49 {j=dfs(adj[i]); 50 low[x]=min(low[x],j); 51 } 52 if (low[x]>=dfn[x]) 53 {con[0]=0; 54 tx++;out++; 55 while (1) 56 {con[++con[0]]=sta[sta[0]]; 57 gid[sta[sta[0]]]=tx; 58 ins[sta[sta[0]]]=0; 59 if (sta[sta[0]]==x) 60 {sta[0]--; 61 break; 62 } 63 sta[0]--; 64 } 65 bool ls; 66 ls=true; 67 for (i=1;i<=con[0];i++) 68 for (j=head[con[i]];j;j=next[j]) 69 if (gid[con[i]]!=gid[adj[j]]) 70 ls=false; 71 if (!ls) out--; 72 else ans=con[0]; 73 } 74 else return low[x]; 75 } 76 int main(){ 77 init();int i,j; 78 for (i=1;i<=n;i++) 79 if (!t[i]) 80 j=dfs(i); 81 if (out>1) 82 printf("0"); 83 else 84 printf("%d",ans); 85 return 0; 86 }