题解-[HAOI]受欢迎的牛

受欢迎的牛

题目在这里--受欢迎的牛

每一头牛的愿望就是变成一头最受欢迎的牛。现在有 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];
}

猜你喜欢

转载自blog.csdn.net/guoyangfan_/article/details/82250631