1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6342 Solved: 3322
[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
Analysis
首先强连通分量缩点,于是这个图肯定成为一个DAG
出度为零的强连通分量就是答案啦
当然,如果有多个点为答案,那么就是错的,受欢迎的牛只有0头
为啥?
Code
1 #include<cstdio> 2 #include<iostream> 3 #define maxn 1000000 4 using namespace std; 5 6 int n,m,de[maxn],ret,ans; 7 int dfn[maxn],low[maxn],TIM,stack[maxn],pos,COL,buck[maxn],color[maxn]; 8 bool vis[maxn]; 9 10 struct edge{ int from,u,v; }e[maxn],E[maxn]; 11 int tot,first[maxn],toT,firsT[maxn]; 12 void insert(int u,int v){ tot++; e[tot].from = first[u]; e[tot].u = u; e[tot].v = v; first[u] = tot; } 13 void inserT(int u,int v){ toT++; E[toT].from = firsT[u]; E[toT].u = u; E[toT].v = v; firsT[u] = toT; } 14 void tarjan(int now){ 15 dfn[now] = low[now] = ++TIM; 16 stack[pos++] = now; vis[now] = true; 17 for(int i = first[now];i;i = e[i].from){ 18 int v = e[i].v; 19 if(!dfn[v]){ 20 tarjan(v); low[now] = min(low[now],low[v]); 21 }else if(vis[v]) low[now] = min(low[now],dfn[v]); 22 }if(dfn[now] == low[now]){ 23 COL++; 24 while(stack[pos-1] != now && pos){ 25 buck[COL]++; 26 color[stack[pos-1]] = COL; 27 vis[stack[--pos]] = false; 28 }color[now] = COL; vis[now] = false; pos--; buck[COL]++; 29 } 30 } 31 32 int main(){ 33 scanf("%d%d",&n,&m); 34 35 for(int i = 1;i <= m;i++){ 36 int x,y; scanf("%d%d",&x,&y); 37 insert(x,y); 38 }for(int i = 1;i <= n;i++) if(!dfn[i]) tarjan(i); 39 40 for(int i = 1;i <= tot;i++){ 41 int u = e[i].u,v = e[i].v; 42 if(color[u] != color[v]){ 43 inserT(color[u],color[v]); 44 de[color[u]]++; 45 } 46 } 47 48 for(int i = 1;i <= COL;i++){ 49 if(!de[i]) ret++,ans = buck[i]; 50 } 51 52 if(ret > 1) cout << 0; 53 else cout << ans; 54 55 return 0; 56 }