洛谷P2746 [USACO5.3]校园网Network of Schools——Tarjan缩点,特判

题目:https://www.luogu.org/problemnew/show/P2746

AC代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

const int MaxN=1e2+5,MaxM=1e4+5;

int n,x,ans1,ans2;
inline int get(){//读入优化 
	char c=getchar();
	int x=0;
	while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9'){
		x=(x<<3)+(x<<1)+c-'0';
		c=getchar();
	}
	return x;
}

int tot,nex[MaxM],from[MaxM],to[MaxM],head[MaxN];
void join(int x,int y){
	nex[++tot]=head[x];
	from[tot]=x;
	to[tot]=y;
	head[x]=tot;
}

int num,dfn[MaxN],low[MaxN],st[MaxN],top,col,co[MaxN],si[MaxN];
void Tarjan(int u){//求SCC 
	dfn[u]=low[u]=++num;
	st[++top]=u;
	for(int i=head[u];i;i=nex[i]){
		int v=to[i];
		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]){//不在上面的for里面!! 
		co[u]=++col;
		++si[col];
		while(st[top]!=u){
			co[st[top]]=col;
			++si[col];
			--top;
		}
		--top;
	}
}

int cd[MaxN],rd[MaxN];
void ReBuild(){//求新图中新点的出度入度 
	for(int i=1;i<=tot;i++){
		int u=from[i],v=to[i];
		if(co[u]!=co[v]){
			cd[co[u]]++;
			rd[co[v]]++;
		}
	}
}

int main(){
	n=get();
	for(int i=1;i<=n;i++)
		while(1) {
			x=get();
			if(!x)break;
			join(i,x);
		}
		
	for(int i=1;i<=n;i++)
		if(!dfn[i])Tarjan(i);
		
	ReBuild();
	
	for(int i=1;i<=col;i++){
		if(rd[i]==0)ans1++;
		if(cd[i]==0)ans2++;
	}
	
	//出度为0的点指向入度为0的点连边,构成回路
	if(col!=1)cout<<ans1<<endl<<max(ans1,ans2);
	else cout<<1<<endl<<0;//特判 
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值