并查集
并查集
并查集有两个操作:
查询:判断两个元素是否为一个连通分量
合并:将两个连通分量合并为一个
并查集用来求连通分量十分方便,通过路径压缩与按秩合并优化,均摊时间复杂度接近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动态更新,最终找到所有连通分量,大大减少查找每一个点所在连通分量的次数

浙公网安备 33010602011771号