并查集是一种可以高效完成以下操作的数据结构:
1.查询元素a与元素b是否属于同一分组。
2.合并元素a和b所属的分组。
对于并查集,每次查询如果不使用路径压缩,在极端情况下将会退化为一条链,如下:
int findfat(int x)
{
if(fat[x] == x) return x;
return findfat(fat[x]);
}
在树型数据结构里,如果发生了退化的情况,那么复杂度就会变得很高,因此合并时要按照一定的规则,此外还要加入如路径压缩过程:
合并过程:
·对于每棵树,记录这棵树的高度(rank)
·合并时,如果两棵树的rank不同,那么从rank小的向rank大的连边
路径压缩过程:
int findfat(int x)//递归写法
{
if(fat[x] == x) return x;
fat[x]=findfat(fat[x]); //加入此句后,对于每次查询,都会在查询过程中将所访问到的点均连接到根结点。
return findfat(fat[x]);
}
int findfat(int x)//非递归写法 更好,因为不会RE
{
int root=x;
while(root != fat[root])//先要找到根节点r
{
root=fat[root];
}
int y=x;
while(y!=root) //从查找节点向上更新结点
{
int fath=fat[y];
fat[y]=root;
y=fath;
}
return r;
}
合并
void unite(int x,int y)
{
x=find(x);
v=find(y);
if(x==y)
return ;
if(rank[x]<rank[y])
par[x]=y;
else
{
par[y]=x;
if(rank[x]==rank[y])
rank[x]++;
}
}
判断是否属于同一集合
bool same(int x,int y)
{
return find(x)==find(y);
}