YbtOJ 强连通分量课堂过关 例2 受欢迎的牛【Tarjan】

在这里插入图片描述


思路

感觉这道题比第一题还简单,首先搞一个Tarjan然后缩点,之后就把整个图跑一边看看有没有出度为0的点(因为只有出度为零的点才能成为明星点)。如果有两个及以上就没有明星奶牛,一个的话就直接输出这个点里面的点的数量就好了。

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
int stack[100010],dfn[100010],low[100010],cnt[100010],tail,sc;
int tot,hd[100010],tot1,hd1[100010],ans[100010],fans;
int v[100010],vq[100010],ru[100010];
int n,m,xxx,y,timen;
struct node
{
	int xx,to,next;
}e[600010];
struct node1
{
	int to,next;
}e1[600010];
void add(int x,int y)
{
	e[++tot]=(node){x,y,hd[x]};
	hd[x]=tot;
}
void add1(int x,int y)
{
	e1[++tot1]=(node1){y,hd1[x]};
	hd1[x]=tot1;
}
void tarjan(int x)
{
	dfn[x]=low[x]=++timen;
	stack[++tail]=x;
	v[x]=1;
	for(int i=hd[x]; i; i=e[i].next)
	 {
	 	int yy=e[i].to;
	 	if(!dfn[yy])
	 	 {
	 	 	tarjan(yy);
	 	 	low[x]=min(low[x],low[yy]);
		 }
		else if(v[yy])
		  low[x]=min(low[x],dfn[yy]);
	 }
	if(dfn[x]==low[x])
	 {
	 	sc++;
	 	while(x!=stack[tail+1])
	 	 {
	 	 	vq[stack[tail]]=sc;
	 	 	cnt[sc]++;
	 	 	v[stack[tail]]=0;
	 	 	tail--;
		 }
	 }
}
int main()
{
	cin>>n>>m;
	for(int i=1; i<=m; i++)
	 {
	   scanf("%d%d",&xxx,&y);
	   add(xxx,y);
	 }
	for(int i=1; i<=n; i++)
	 if(!dfn[i])
	   tarjan(i);
	for(int i=1; i<=m; i++)    //缩点
	 {
	 	if(vq[e[i].xx]!=vq[e[i].to])
	 	 {
	 	   add1(vq[e[i].xx],vq[e[i].to]);
	 	   ru[vq[e[i].xx]]++;
		 }
	 }
	int bj=0;
	for(int i=1; i<=sc; i++)
	 if(!ru[i])
	  {
	  	 if(bj)
	  	  {
	  	    cout<<0;
	  	    return 0;
		  }
		 else
		   bj=i;
	  }
	cout<<cnt[bj];
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值