并查集
什么是并查集
并查集是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。
——摘自oiwiki
简单来说,并查集是一种可以快速求出一个元素的祖先的数据结构
并查集的初始化
通常,我们将每个节点的 $f_i$ 设为自己,即 $i$。
for(int i=1;i<=n;i++) f[i]=i;
并查集的查询(普通)
通过不断递归来查找元素所在的根
int find(int x){
if(f[x] == x) return x;
return find(f[x]);
}
这种情况下,如果树的高度很大,那么单次查询的时间复杂度为 $O(n)$
并查集的查询(路径压缩)
每次查询之后直接将此节点接在集合代表节点的下方,以后的查询就是 $O(1)$ 的了。均摊时间复杂度为 $O(\log n)$
int find(int x){
if(f[x]==x)return x;
f[x]=find(f[x]);
return f[x];
}
并查集的合并
可以理解为将一个并查集接在另一个并查集的根节点上
void move(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy){
f[fx]=fy;
}
}
带权并查集
即边权带值的并查集。
即一个并查集在合并,查询的过程中还需要维护边权上的权值总和。
例题: