传送门,并查集

如何才能穿过传送门

https://ac.nowcoder.com/acm/problem/236870

一开始想的是要到终点一定是一直向右走,结果因为评测数据有误,没过。。

然后我思考了一下,传送门限制的是一个点的左右两端能否互通,所以只要把除了0和n的每个点分成左右两个部分然后遍历一遍用并查集维护最后判断一下fd(0)和fd(n)是否相等,比起一直向右走,很容易想到这样一定是对的,路径压缩之后复杂度为o(n)。

写完提交之后,我诧异地发现,之前的向右走过了,这个并查集也过了。。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n,m,k,ans,q,to[10010],A[10010],fa[10010],x,y;
ll fd(ll a){
	ll b=a;
	while(a!=fa[a]){
		a=fa[a];
	}
	fa[b]=a;
	return a;
}
void hb(ll a,ll b){
	fa[fd(b)] =fd(a);
	return;
}
int main(){
	cin>>n>>m>>q;
	for(int i=1;i<=3*n;i++){
		fa[i]=i;
		to[i]=i;
	}
	for(int i=1;i<=m;i++){
		scanf("%lld%lld",&x,&y);
		to[x]=y;
		to[y]=x;
		hb(x,y+n);
		hb(x+n,y);
	}
	for(int i=1;i<=q;i++){
		scanf("%lld",&x);
		to[x]=0;
	}
	hb(0,1);
	for(int i=1;i<=n;i++){
		if(to[i]==i) hb(i,i+n);
		if(to[i-1]!=0) hb(i-1+n,i);	
	}
	//cout<<fd(49)<<" "<<fd(50)<<" "<<fd(51)<<endl;
	if(fd(0)==fd(n)){
		cout<<"YES";
	}
	else cout<<"NO";
	return 0;
} 
全部评论

相关推荐

2024-12-28 20:22
西安交通大学 Java
携程 酒店部门 25*15,留学生补贴 计算机科班
点赞 评论 收藏
分享
jack_miller:我给我们导员说我不在这里转正,可能没三方签了。导员说没事学校催的时候帮我想办法应付一下
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务