NKOJ P7842 疫情防控

8 篇文章 0 订阅
文章讨论了一种图的特性,即每个城市由且仅由一条单行道路进入。若图联通,必须存在环以满足条件;若图不联通,则每个连通块内部需有环。解决方案利用了并查集数据结构,通过vis数组标记连通块是否存在环,在合并连通块时判断环的存在性。最终,检查所有连通块是否都包含环来确定答案。
摘要由CSDN通过智能技术生成

题面

分析

这道题的本质就是找可以使得每座城市有且仅有一条道单行路进入该市的图有什么特点;

首先,我们假设图联通,则由于每个城市只有一条单行道可以进入,即一个城市必须有且仅有一条单行道与之配对,所以这个图至少要有 n n n条边,即图中必须要有环才可以满足要求!

那如果图不连通了?也很好办,把这个图拆成若干个连通块,每个连通块单独考虑,即每个连通块中必须有环! 这就很好办了,只需要一个带权并查集即可;

再来考虑一下并查集,我们用vis[i]的真假表示祖先为 i i i 的连通块是否有环;则在添边时如果当前边的两个端点早就在同一个连通块中,则把这个连通块的vis标记为真,如果这条边连接了两个不一样的连通块 ( i , j ) (i,j) (i,j),则有:

vis[getfather(i)]=vis[getfather(j)]|vis[getfather(i)];

这是因为只要两个连通块中有一个有环,则合并后的大连通块一定包含一个环;

最后就是实现的细节问题了;

Ac Code

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
int father[100005],vis[100005];
int n,m;
int get(int son){
	if(father[son]==son){return son;}
	return father[son]=get(father[son]);
} 
void onion(int x,int y){
	int fx=get(x);int fy=get(y);
	if(fx==fy){vis[fx]=vis[fy]=1;return;}
	father[fx]=fy;
	vis[fy]=vis[fx]|vis[fy];
	return;
}
signed main(){
	scanf("%lld%lld",&n,&m);
	for(register int i=1;i<=n;i++){father[i]=i;}
	for(register int i=1;i<=m;i++){int x,y;scanf("%lld%lld",&x,&y);onion(x,y);}
	for(register int i=1;i<=n;i++){if(!vis[get(i)]){printf("NO\n");return 0;}}
	printf("YES\n");return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值