传送门,并查集
如何才能穿过传送门
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;
}