POJ1703并查集(区分两个集合)
Posted liyeixn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ1703并查集(区分两个集合)相关的知识,希望对你有一定的参考价值。
题意:输入n,m。n个人,m个规定/询问。一共有两个集合,A:询问a,b是否在同一个集合?D:表明a,b不在同一个集合。输出有三种,不在同一集合,在同一集合,不确定。
解析:其实有点离散化的意思。传统并查集是合并两个集合,而这个题是分开两个集合。那么可以这么做,想办法进行合并操作。输入a,b,a,b没有了关系,但是可以规定,a+n,b属同一集合,a,b+n属于同一集合。即,n右边a+n的那些和b放入同一集合,n右边b+n的那些和a放入同一集合,这样a,b就撇开了关系。就可以进行join()操作了。判断过程具体看代码吧。输入注意一下
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<map> using namespace std; typedef long long ll; const int maxn=2e5+1000; int pr[maxn]; //int vis[maxn]; int sum=0; int n,m; int find(int x){ while(x!=pr[x]) { pr[x]=pr[pr[x]]; x=pr[x]; } return x; } void join(int x1,int x2) { int f1=find(x1),f2=find(x2); if(f1!=f2) { pr[f1]=f2; } return ; } void first() { for(int i=0;i<=n*2+10;i++) { pr[i]=i; } } bool check(int a,int b) { int f1=find(a),f2=find(b); // cout<<f1<<"-"<<f2<<endl; if(f1==f2) { return true; } return false; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); first(); char ch,ch2; while(m--) { // cin>>ch; int x,y; scanf("%c",&ch); scanf("%c%d%d",&ch,&x,&y); if(ch==\'D\') { join(x+n,y); join(x,y+n); } else { if(check(x,y)||check(x+n,y+n)) //如果x+n,x+n属于同一个集合,那么a,b之前肯定记录过而且同属一个集合。 cout<<"In the same gang."<<endl; else if(check(x+n,y)||check(y+n,x)) //如果x+n和y同属一个集合或者y+n和x同属一个集合,那么x,y肯定同属一个集合了。 cout<<"In different gangs."<<endl; else cout<<"Not sure yet."<<endl; //否则就不确定 } } } }
以上是关于POJ1703并查集(区分两个集合)的主要内容,如果未能解决你的问题,请参考以下文章
[POJ1703]Find them, Catch them(并查集)
poj1703 Find them, Catch them(带权并查集)