受欢迎的牛(强连通分量)

Posted SSL_LKJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了受欢迎的牛(强连通分量)相关的知识,希望对你有一定的参考价值。

受欢迎的牛

在这里插入图片描述

解题思路

先缩点成一个有向无环图
如果只有一个出度为0的点
那么这个新图中出度为0的点所代表的牛都是明星
输出该强连通分量中的点数
否则没有牛成为明星
输出0

AC代码

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,ok,top,tot,ans,T,TT,du[50005],low[50005],col[50005],dfn[50005],sum[50005],stak[50005],head[50005];
struct node
{
	int to,next;
}a[50005];
void add(int x,int y)//建边
{
	a[++tot]=(node){y,head[x]};
	head[x]=tot;
}
void Tarjan(int x)//求强连通分量缩点
{
	dfn[x]=low[x]=++T;
	stak[++top]=x;
	for(int i=head[x];i;i=a[i].next)
	{
		int v=a[i].to;
		if(!dfn[v])
		{
			Tarjan(v);
			low[x]=min(low[x],low[v]);
		}
		else if(!col[v])low[x]=min(low[x],low[v]);
	}
	if(dfn[x]==low[x])
	{
		col[x]=++TT;
		sum[TT]=1;
		while(stak[top]!=x)
		 sum[TT]++,col[stak[top--]]=TT;
		top--;
	}
	return;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
	}
	for(int i=1;i<=n;i++)
	 if(!dfn[i])Tarjan(i);
	for(int i=1;i<=n;i++)
	 for(int j=head[i];j;j=a[j].next)//枚举
	 {
	 	int v=a[j].to;
	 	if(col[i]!=col[v])du[col[i]]++;
	 }
	for(int i=1;i<=TT;i++)
	 if(!du[i])ans=sum[i],ok++;
	if(ok!=1)printf("0");
	else printf("%d",ans);
	return 0;
}

谢谢

以上是关于受欢迎的牛(强连通分量)的主要内容,如果未能解决你的问题,请参考以下文章

P2341 [HAOI2006]受欢迎的牛|模板强连通分量(tarjan)

受欢迎的牛

[HAOI2006]受欢迎的牛 G-强连通分量

[HAOI2006]受欢迎的牛 [强连通分量]

bzoj1051: [HAOI2006]受欢迎的牛(强联通)

Luogu P2341 [HAOI2006]受欢迎的牛