【Ybtoj 第15章例2】受欢迎的牛【强连通分量】【Tarjan缩点】

67 篇文章 0 订阅
9 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


解题思路

首先我们按照题目给出的喜欢关系建一张有向图。

任意一个强连通点对代表的牛都互相喜欢,由此,我们将原图进行缩点,得到一个新的有向无环图,显然一头奶牛能成为一个明星的必要条件有

  1. 位于出度为0的强连通分量中(若其出度不为0,那么他的出边指向的强连通分量中的牛一定不喜欢它)
  2. 出度为0的强连通分量只有它所在的唯一一个。(否则,没有妞会成为明星)

所以,将原图缩点的有向无环图图中,如果只有一个出度为0的点,那么这个点所代表的牛都是明星,输出该连通分量中的点数;否则没有牛是明星,输出0.


代码

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;

int n,m,u,v,k,tot,t,top,ans,lyx;
int h[100010],dfn[10010],low[10010],st[10010],c[10010],sum[10010],du[10010];

struct c{
	int x,next;
}a[100010];

void add(int x,int y){
	a[++k].x=y;
	a[k].next=h[x];
	h[x]=k;
}

void Tarjan(int x)
{
	st[++top]=x;
	dfn[x]=low[x]=++t;
	for(int i=h[x];i;i=a[i].next)
	{
		int y=a[i].x;
		if(!dfn[y])
		{
			Tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(!c[y])
			low[x]=min(low[x],low[y]);
	}
	if(dfn[x]==low[x])
	{
		tot++;
		while(st[top+1]!=x)
		{
			c[st[top]]=tot;
			sum[tot]++;
			top--;
		}
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		add(u,v);
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i])
			Tarjan(i);
	for(int i=1;i<=n;i++)
	{
		for(int j=h[i];j;j=a[j].next)
		{
			int y=a[j].x;
			if(c[i]!=c[y])
				du[c[i]]++;
		}
	}
	for(int i=1;i<=tot;i++)
	{
		if(!du[i])
		{
			lyx++;
			ans=sum[i];
		}
	}
	if(lyx==1)
		printf("%d",ans);
	else printf("0");
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值