- 并查集算法(union_find sets)不支持分割一个集合,求连通子图、求最小生成树
- 并查集由pre[]数组和两个函数find(),join()组成,find()是寻找根节点,join()是连接两个根节点,合并路线的。
- 模板:
初始化,建立子树
我们将每一个结点的前导结点设置为自己,如果在join函数时未能形成连通,将独立成点。
for(int i=0;i<1000;++i)
{
pre[i]=i; //初始化,建立各个孤立的子树
}
find()函数
int pre[1000];
//记得初始化
int find(int x) //寻找x的根节点
{
int r=x;
while(pre[r]!=r){ //r不是根节点,就继续以r往上找
r=pre[r];
}
int i=x,j;
while(pre[i]!=r) //路径压缩
{
j=pre[i]; //j暂时储存i的父节点
pre[i]=r; //更新i的父节点
i=j;
}
return r; //返回根节点
}
递归:
int find(int x)
{
if(pre[x]!=x)
{
pre[x] = find(pre[x]);
}
return pre[x];
}
路径压缩为了加快查找的速度,将x点与其根节点直接相连,构造成类似于只有叶子结点而没有分支结点的树
这里需要注意带权值的并查集,循环和递归有很大区别(递归数据更新从根结点开始向下更新,而循环是从子节点一直向上更新),建议用递归。
join()函数
void join(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
{
pre[fx]=fy; //将x,y连起来,两个子树的根节点谁做根节点无关紧要
}
}
这里是一篇有意思的博客:https://blog.csdn.net/the_best_man/article/details/62416938