受欢迎的牛
题目在这里--受欢迎的牛
每一头牛的愿望就是变成一头最受欢迎的牛。现在有 N 头牛,给你 M对整数 (A,B),表示牛 A 认为牛 B 受欢迎。这种关系是具有传递性的,如果 A 认为 B 受欢迎,B认为 C受欢迎,那么牛 A 也认为牛 C 受欢迎。你的任务是求出有多少头牛被除自己之外的所有牛认为是受欢迎的。
输入格式
第一行两个数 N,M;
接下来 M 行,每行两个数 A,B,意思是 A 认为 B 是受欢迎的(给出的信息有可能重复,即有可能出现多个 A,B)。
输出格式
输出被除自己之外的所有牛认为是受欢迎的牛的数量。
样例
样例输入
3 3
1 2
2 1
2 3
样例输出
1
样例说明
只有第三头牛被除自己之外的所有牛认为是受欢迎的。
数据范围与提示
对于全部数据,1≤N≤10^4,1≤M≤5×10^4。
这是一道很明显的强连通分量(广告一下:我的强连通分量blog)。在有向图中找强连通子图,并将它们所点。整个图就成为了有向无环图。之后,如果只有一个出度为0的点,就将它中(停顿)牛的数量输出。大于1的话则输出0,因为大于1时就不再是强连通了。
#include<bits/stdc++.h>
using namespace std;
struct node{
int to,next;
};
node edge[50005];
int index1,head[10005],tot,f[10005],vis[10005],st[10005],dfn[10005],low[10005],top,num[10005],cnt,size[10005];
//size数组记录缩点后共有牛的数量;
//f数组记录两个点是否处于同一个强连通分量里面;
//dfn、low不解释。
//num数组记录每个点的出度;
inline void add(int x,int y)
{
edge[++tot].to=y;
edge[tot].next=head[x];
head[x]=tot;
}
inline void tarjan(int u)
{
dfn[u]=low[u]=++index1;
st[++top]=u;
vis[u]=1;
for(register int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
low[u]=min(low[u],dfn[v]);
}
int now;
if(low[u]==dfn[u])
{
++cnt;
do{
now=st[top--];
size[cnt]++;
f[now]=cnt;
vis[now]=0;
}while(u!=now);
}
}
int main()
{
int n,m;
cin>>n>>m;
for(register int i=1;i<=m;++i)
{
int a,b;
cin>>a>>b;
add(a,b);
}
for(register int i=1;i<=n;++i)
if(!dfn[i])tarjan(i);
for(register int i=1;i<=n;++i)
for(register int j=head[i];j;j=edge[j].next)
if(f[i]!=f[edge[j].to])
num[f[i]]++;
int ans=0;
for(register int i=1;i<=cnt;++i)
if(!num[i])
{
if(ans){
cout<<0<<endl;
return 0;
}
else ans=i;
}
cout<<size[ans];
}