📅  最后修改于: 2023-12-03 14:55:38.283000             🧑  作者: Mango
树上的不相交集合(Disjoint Set Union on a Tree,DSU on Tree)是在线段树/平衡树等数据结构之上的一种数据结构。该数据结构类似于各种不相交集合的实现,用于在树上维护各个点所在集合的信息,支持在树上进行节点的合并和查询祖先等操作。
该数据结构看起来类似于并查集,但是使用了路径压缩的优化,使得树上合并和查询的时间复杂度为 O(logn)。
通常情况下,数据结构的实现包括以下字段:
parent[]
:记录每个节点的父节点。rank[]
:记录每个节点所在集合的大小,可以用作优化。cnt
:当前集合的数量。其中, rank[]
和 cnt
可以不需要,具体实现时可以选择不使用。
该数据结构主要支持以下操作:
find(x)
:查找 x
所在的集合的代表节点(即根节点)。merge(x, y)
:将 x
所在的集合和 y
所在的集合合并。query(x, y)
:查询 x
到 y
路径上的祖先中所在集合的代表节点。例如,如果两个节点在同一集合中,则该操作返回它们的最近公共祖先。下面是一个简单的实现:
struct DSU {
int parent[MAXN], rank[MAXN], cnt;
void make_set(int n) {
for(int i = 1; i <= n; i++) {
parent[i] = i;
rank[i] = 1;
}
cnt = n;
}
int find(int x) {
if(parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
void merge(int x, int y) {
int px = find(x), py = find(y);
if(px == py) return;
if(rank[px] < rank[py]) swap(px, py);
parent[py] = px;
rank[px] += rank[py];
cnt--;
}
int query(int x, int y) {
while(find(x) != find(y)) {
if(rank[find(x)] < rank[find(y)]) swap(x, y);
x = parent[find(x)];
}
return find(x);
}
} dsu;
树上的不相交集合数据结构可以应用于多种场景,例如: