并查集

并查集
并查集有两个操作:
查询:判断两个元素是否为一个连通分量
合并:将两个连通分量合并为一个
并查集用来求连通分量十分方便,通过路径压缩与按秩合并优化,均摊时间复杂度接近O(1),可处理数据范围为1e6,求连通分量时可以无脑用并查集。
实现方式:
首先需要两个数组,分别表示当前点连接那个点,当前点被多少个点连接的“权重“
 
vector<int> ti(n+1);
vector<int> size(n+1,1);//全部初始化为1
 
存连接下一个点的数组记得把初始值指向自己
 
for(int i=1;i<=n;i++){
        ti[i]=i;
    }
 
然后把产生边的两点传入bin函数处理
 
    for(int i=1;i<=n;i++){
        cin>>u>>v;
        bin(u,v);
    }
 
实现并查集的函数分成了两部分:
Root函数先找到当前单独x点所处连通分量的根节点,然后做路径压缩,最后将这个连通分量指向自己的点传回bin函数
(路径压缩:将连通分量里所有点都指向根节点,减少查询次数)
Bin函数中将v与u所在的连通分量合并,增加根节点的权重,注意是小树并到大树中
 
int root(int x){
    int mid=x;
    while(ti[mid]!=mid){//寻找根节点
        mid=ti[mid];
    }
    while(ti[x]!=mid){//路径压缩
        int tt=ti[x];
        ti[x]=mid;
        x=tt;
    }
    return mid;
}
void bin(int x,int y){
    int x1=root(x);//获得当前连通分量的根节点,顺便进行状态压缩
    int y1=root(y);
    if(x1!=y1){//如果两个点已经在同一个连通分量,就可以不执行合并操作
        if(size[x1]<size[y1])swap(x1,y1);
        ti[y1]=x1;
        size[x1]+=size[y1];//增加根节点的权重
    }
}
 
如果要查询,只需向root传入点,root函数会返回点所在的连通分量

 

并查集随着传入的v,u动态更新,最终找到所有连通分量,大大减少查找每一个点所在连通分量的次数

posted @ 2025-05-26 21:56  洛鸿  阅读(24)  评论(0)    收藏  举报