浅谈——并查集

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace  std;
    
int fa[10010];//fa[i] = a:保存a的祖先 
int m,n,k = 0;
int aa,bb,cc;
char ma[200010];

int find(int a){//查找a的祖先 
    if(fa[a] == a)//如果a的祖先是a,即a就是祖先 
    return a;//返回祖先a 
    else return fa[a] = find(fa[a]);//a的祖先就是a的祖先的祖先,实现一直溯源 
    //这个操作叫做路径压缩,是优化的思路 
}

void join(int x,int y){//判断x,y的祖先是不是一个祖先 
    int fx = find(x);//查找x的祖先 
    int fy = find(y);//查找y的祖先
    if(fx != fy)//如果x,y的祖先不是一个祖先 
    fa[fx] = fy;//就让y的祖先成为a的祖先,即合并x,y 
}

int main(){
    scanf("%d %d",&n,&m);
    for(int i = 0;i < n;i++){
        fa[i] = i;//对祖先数组初始化 
    }
    for(int i = 0;i < m;i++){
        scanf("%d %d %d",&aa,&bb,&cc);
        if(aa == 1)//要实现归并操作 
        join(bb,cc);//归并二者 
        else//要实现查找操作 
        if(find(bb) == find(cc)){//如果二者的祖先是一个祖先 
            ma[k] = 'Y';//那么输出’y' 
            k++;//记录查找的次数 
        }
        else{//如果二者的祖先不是一个祖先
            ma[k] = 'N';//那么输出’n'
            k++;//记录查找的次数
        }
    }
    for(int i = 0;i < m;i++){//按照输出的次数分别输出 
        printf("%c
",ma[i]);
    }
    return 0;
}

我知道你们都很强...我就不讲了...

快来看代码吧!我的代码很详细的!

下面就是带权并查集了!

粘一下基本思想!

int pa[100005],d[100005];
int gpa(int x) {
    int t = pa[x];
    pa[x] = gpa(t);
    d[x] ^= d[t];//如果d[x]与d[t]一样,就返回0;不一样,就返回1 
    return pa[x]; 
} 

void Merge(int x,int y) {
    int fx = gpa(x);
    int fy = gpa(y);
    if(fx != fy) pa[fx] = fy;
    return; 
}

int query(int x,int y) {
    int fx = gpa(x),fy = gpa(y);
    return d[x] ^ d[y];
}
//注意递归边界问题 

最后推荐一个大佬的blog:paopo!
如果带权并查集大家有问题,欢迎看他的blog!

原文地址:https://www.cnblogs.com/rabbit-byt/p/10066506.html