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;  //否则就不确定
            }
        }
    }
}

  

猜你喜欢

转载自www.cnblogs.com/liyexin/p/12530816.html
今日推荐