并查集
Posted tomato1001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集相关的知识,希望对你有一定的参考价值。
并查集是一种用来管理元素分组情况的数据结构,可以高效的执行下面的操作:
1.查寻(find):查询元素a和b是否属于同一分组;
2.合并(union):将两个不同的分组合并为一个分组。
注意并查集虽然可以进行合并操作,但是却无法进行分割操作。
并查集的结构
并查集使用树形结构实现,整个并查集由一颗或多棵树构成,每棵树代表一个分组。在并查集中,哪个节点是哪个节点的父亲以及树的形状等信息并不重要,整体形成一个树状结构才是关键。但是,在实际应用中,我们通常使用每个分组的根节点代表分组编号。
初始化
并查集初始状态是每个元素都属于自身的子集,即每个子集仅有一个元素。
int fa[MAXN]; // 记录每个元素的父亲,初始化就是将每个元素的父亲设置为自身
void makeSet(int size) {
for (int i = 1; i <= size; i++)
fa[i] = i;
}
查询分组
查找就是查看每个元素属于哪个分组,即通过该节点不断的查看自己的父亲,直到找到根节点。
int find(int x) {
if (fa[x] == x)
return x;
return find(fa[x]);
}
合并
合并就是将两个分组合并为一个分组,首先找到两个分组的根,然后从一个分组的根向另一个分组的根两边,这样,两棵树就成为了一颗树,也就把两个组合并为一个组了。
void unionSet(int x, int y) {
x = find(x);
y = find(y);
if(x != y)
fa[x] = y;
}
查询
查询两个元素是否属于同一个分组,我们仅需找到两个元素所在分组的根节点,判断是否为同一个即可。
优化
并查集采用了树状结构实现,如果树的高度越来越高,查询的效率也会越来越低。为了避免退化,我们可以考虑将高度较小的分组合并到高度较大的分组,下面就是考虑了高度的合并。
此外,在中间节点没有影响的情况下,也可以通过路径压缩来减小树的高度。路径压缩就是一旦向上走到了一次根节点,就把这个点到父亲的边改为直接连向根。
int find(int x) {
if (fa[x] == x)
return x;
int p = find(fa[x]);
fa[x] = p;
return p;
}
以上是关于并查集的主要内容,如果未能解决你的问题,请参考以下文章