PKU2186 Popular Cows 受欢迎的牛
Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N(N<=10000)头牛,给你M(M<=50000)对整数(A,B),表示牛A认为牛B受欢迎。这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。
接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复)
N<=10000,M<=50000
接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复)
N<=10000,M<=50000
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1 题解:tarjan模板题。 首先用tarjan算法求出所有的强连通分量,然后将每个强连通分量缩成一点,则形成一个有向无环图DAG。 DAG上面有唯一的出度为0的点,则该点能被所有的点到达。那么该点所代表的强连通分量里的所有的点都能被原图中的任意一点可达,则该强连通分量里的点的个数,就是答案。 如果DAG上有不止一个出度为0的点,则无解(这是肯定的)。缩点的时候不一定要构造新图,只要把不同强连通分量的点染不同颜色,然后考察各种颜色的点有没有连到别的颜色的边即可(即其对应的缩点后的DAG图上的点是否有出边)。 最后附上代码:#include<bits/stdc++.h> using namespace std; int n,m,ans,group,cnt,top,total; int belong[10010],du[10010],first[10010],dfn[10010],low[10010],st[10010]; struct node { int s,e,next; }v[50050]; int read() { int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void tarjan(int k) { dfn[k]=++cnt; low[k]=cnt; st[++top]=k; int ttt=top; for(int i=first[k];i;i=v[i].next) if(!belong[v[i].e]) { if(!dfn[v[i].e])tarjan(v[i].e); low[k]=min(low[k],low[v[i].e]); } if(dfn[k]==low[k]) { ++total; for(int i=ttt;i<=top;i++) belong[st[i]]=total; top=ttt-1; } } int main() { n=read();m=read(); for(int i=1;i<=m;i++) { v[i].s=read();v[i].e=read(); v[i].next=first[v[i].s]; first[v[i].s]=i; } for(int i=1;i<=n;i++) if(!belong[i])tarjan(i); for(int i=1;i<=m;i++) if(belong[v[i].s]!=belong[v[i].e])++du[belong[v[i].s]]; for(int i=1;i<=total;i++) if(!du[i])++ans,group=i; if(ans!=1)printf("0"); else { ans=0; for(int i=1;i<=n;i++) if(belong[i]==group)++ans; printf("%d",ans); } return 0; }