并查集

这个有时候做关于图的时候会用的到,比如要建成一颗最小生成树,这个并查集就能够用上了,它的作用就大了,可以判断两个点之间是否连通,当两个点之间联通了就说明他们是以集合里面的,也可以用亲戚关系来表达,三个原本互相不认识的人聚到了一起,他们分别是A,B,C;随着三人之间的更加熟悉,A和B是亲戚关系(即A和B之间是连通的),B和C之间也是亲戚关系,所以A和C之间也是亲戚,所以A、B、C都是亲戚关系,即他们都是连通的,这个时候我们怎么知道他们三个是亲戚关系?只需要从他们之中找出一个代表,就相当于氏族族长,你凭什么说你们就是一个家族的,我们的族长是一样的,这样就能够知道了。为了方便,我们把每次最后一个进入家族的当做族长,代码如下。

#include<iostream>
using namespace std;
const int H=1e5+3;
int fa[H];
void build(int N)//初始化,N个人都是互相不认识的
{
    for(int i=1;i<=N;i++){
        fa[i]=i;
    }
    return ;
}
int find(int x)//找到x的族长是谁
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
bool che(int x,int y)//判断x,y是不是一个族的
{
    return find(x)==find(y);
}
void mer(int x,int y)//如果x,y不是一个族的,就把他们并入到一个家族中
{
    if(!che(x,y)){
        fa[fa[x]]=fa[y];
    }
    return ;
}
int main()
{
    int N,M;
    cin >> N >> M;//N代表有几个人,M代表他们之间有几种关系(一对一的)
    build(N);
    for(int i=0;i<M;i++){
        int x;
        int y;
        cin >>x >> y;
        mer(x,y);
    }
    int p;//输入p组x和y的关系,如果是一个家族的就输出Yes,否则输出No
    cin >> p;
    for(int i=0;i<p;i++){
        int x;
        int y;
        cin  >> x >> y;
        if(che(x,y)){
            cout << "Yes" << endl;
        }
        else{
            cout << "No" << endl;
        }
    }
    return 0;
}

 

posted @ 2019-04-16 19:50  srcrs  阅读(115)  评论(0编辑  收藏  举报