LOJ #10091. 「一本通 3.5 例 1」受欢迎的牛

https://loj.ac/problem/10091

题目描述

原题来自:USACO 2003 Fall

每一头牛的愿望就是变成一头最受欢迎的牛。现在有 NNN 头牛,给你 MMM 对整数 (A,B)(A,B)(A,B),表示牛 AAA 认为牛 BBB 受欢迎。这种关系是具有传递性的,如果 AAA 认为 BBB 受欢迎,BBB 认为 CCC 受欢迎,那么牛 AAA 也认为牛 CCC 受欢迎。你的任务是求出有多少头牛被除自己之外的所有牛认为是受欢迎的。

输入格式

第一行两个数 N,MN,MN,M;
接下来 MMM 行,每行两个数 A,BA,BA,B,意思是 AAA 认为 BBB 是受欢迎的(给出的信息有可能重复,即有可能出现多个 A,BA,BA,B)。

输出格式

输出被除自己之外的所有牛认为是受欢迎的牛的数量。

样例

样例输入

3 3
1 2
2 1
2 3

样例输出

1

样例说明

只有第三头牛被除自己之外的所有牛认为是受欢迎的。

数据范围与提示

对于全部数据,1≤N≤104,1≤M≤5×1041\le N\le 10^4,1\le M\le 5\times 10^41≤N≤104,1≤M≤5×104。

当这是一棵树的时候,很容易看出求每个点的出度,输出是否存在出度为0的点

(如果有多个结点,是不可能有奶牛被其余牛都欢迎,答案为0)

但这是一个有向图,所以要缩点后进行如上的操作

#include<cstdio>
#include<iostream>
using namespace std;
int read()
{
	int ret=0;
	char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9')
		ret=(ret<<1)+(ret<<3)+ch-'0',ch=getchar();
	return ret;
}

const int N=1e6+4;
int n,m,a[N],d[N],ans;
int he[N],to[N],nxt[N],cnt;
int dfn[N],sgn,low[N],st[N],top,co[N],col;
struct NA{
	int u,v;
}e[N];

inline void add(int u,int v)
{
	to[++cnt]=v;
	nxt[cnt]=he[u];
	he[u]=cnt;
}

void Tarjan(int u)
{
	dfn[u]=low[u]=++sgn;
	st[++top]=u;
	for(int e=he[u];e;e=nxt[e])
	{
		int v=to[e];
		if(!dfn[v]) 
			Tarjan(v),low[u]=min(low[u],low[v]);
			else if(!co[v]) 
				low[u]=min(low[u],dfn[v]); 	
	}	
	if(dfn[u]==low[u])
	{
		co[u]=++col;
		while(top&&st[top]!=u)
			co[st[top--]]=col;
		top--;
	}
}

int main()
{
	n=read(),m=read();
	for(int i=1;i<=m;i++)
		e[i].u=read(),e[i].v=read(),
		add(e[i].u,e[i].v);
	for(int i=1;i<=n;i++)
		if(!dfn[i]) Tarjan(i);
	for(int i=1;i<=n;i++)
		a[co[i]]++;
	for(int i=1;i<=m;i++)
		if(co[e[i].v]!=co[e[i].u])
			d[co[e[i].u]]++;
	for(int i=1;i<=col;i++)
		if(!d[i])
		{
			if(!ans) ans=a[i];
				else 
				{
					ans=0; break;
				}
		}
	printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/YYHS_WSF/article/details/83053704