[BZOJ1051][HAOI2006] 受欢迎的牛 tarjan求联通分量
1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5687 Solved: 3016
[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
我们可以对于这个图进行tarjan求强联通分量并缩点,对于缩点后的每一个点,若他是唯一出度为0的点,就说明他之中的所有牛被众人%膜拜%,否则无解。
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdlib> 7 using namespace std; 8 struct data 9 { 10 int next,to; 11 }e[100001],e1[100001]; 12 int n,m; 13 int head[50005],cnt,head1[50005],cnt1; 14 int dfn[50005],low[50005]; 15 bool vis[50005],inq[50005]; 16 int q[50005],top; 17 int tim; 18 int scc; 19 int size[50005]; 20 int belong[50005]; 21 void add(int u,int v){e[cnt].next=head[u];e[cnt].to=v;head[u]=cnt;cnt++;} 22 void add1(int u,int v){e1[cnt1].next=head1[u];e1[cnt1].to=v;head1[u]=cnt1;cnt1++;} 23 void dfs(int now) 24 { 25 dfn[now]=low[now]=++tim; 26 vis[now]=inq[now]=1; 27 q[++top]=now; 28 for(int i=head[now];i>=0;i=e[i].next) 29 { 30 int to=e[i].to; 31 if(!vis[to]) 32 { 33 dfs(to); 34 low[now]=min(low[to],low[now]); 35 } 36 else if(inq[to]) low[now]=min(low[now],dfn[to]); 37 } 38 if(low[now]==dfn[now]) 39 { 40 scc++; 41 int c=0; 42 while(c!=now) 43 { 44 c=q[top--]; 45 inq[c]=0; 46 belong[c]=scc; 47 size[scc]++; 48 } 49 } 50 } 51 void rebuild() 52 { 53 memset(head1,-1,sizeof(head1)); 54 for(int i=1;i<=n;i++) 55 for(int j=head[i];j>=0;j=e[j].next) 56 { 57 int to=e[j].to; 58 if(belong[i]!=belong[to]) add1(belong[i],belong[to]); 59 } 60 } 61 void tarjan() 62 { 63 for(int i=1;i<=n;i++) if(!vis[i]) dfs(i); 64 rebuild(); 65 } 66 void work() 67 { 68 int ans=0; 69 for(int i=1;i<=scc;i++) 70 { 71 if(head1[i]==-1) 72 { 73 if(ans){ans=0;cout<<ans;return ;} 74 else{ans=size[i];} 75 } 76 } 77 cout<<ans; 78 } 79 int main() 80 { 81 memset(head,-1,sizeof(head)); 82 scanf("%d%d",&n,&m); 83 for(int i=1;i<=m;i++) 84 { 85 int u,v; 86 scanf("%d%d",&u,&v); 87 add(u,v); 88 } 89 tarjan(); 90 work(); 91 } 92
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~