📜  树上的不相交集联合|套装1(1)

📅  最后修改于: 2023-12-03 14:55:38.283000             🧑  作者: Mango

树上的不相交集合数据结构

概述

树上的不相交集合(Disjoint Set Union on a Tree,DSU on Tree)是在线段树/平衡树等数据结构之上的一种数据结构。该数据结构类似于各种不相交集合的实现,用于在树上维护各个点所在集合的信息,支持在树上进行节点的合并和查询祖先等操作。

数据结构

该数据结构看起来类似于并查集,但是使用了路径压缩的优化,使得树上合并和查询的时间复杂度为 O(logn)。

通常情况下,数据结构的实现包括以下字段:

  1. parent[]:记录每个节点的父节点。
  2. rank[]:记录每个节点所在集合的大小,可以用作优化。
  3. cnt:当前集合的数量。

其中, rank[]cnt 可以不需要,具体实现时可以选择不使用。

主要操作

该数据结构主要支持以下操作:

  1. find(x):查找 x 所在的集合的代表节点(即根节点)。
  2. merge(x, y):将 x 所在的集合和 y 所在的集合合并。
  3. query(x, y):查询 xy 路径上的祖先中所在集合的代表节点。例如,如果两个节点在同一集合中,则该操作返回它们的最近公共祖先。
代码实现

下面是一个简单的实现:

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;
应用场景

树上的不相交集合数据结构可以应用于多种场景,例如:

  • 树链剖分
  • 树形动态规划
  • 树的直径 等等。