PrepStack · Markdown HTML

并查集动态连通性

并查集、MST 与离线激活 · HTML

数学 / 逻辑形态

对象集 V 上执行 union(a,b)、find(x)、connected(a,b);关系是等价关系,边只增加。

识别信号

容易误判的相似信号

SignalWhy it is different
需要路径或距离DSU 丢弃图内路径;应使用 BFS、Dijkstra 或显式图。
任意在线删边普通 DSU 不能拆集合;考虑倒序离线、rollback DSU 或动态连通结构。

核心不变量

每个集合是一棵父指针树,根是唯一代表元;size 仅在根处有效。

状态、转移与处理顺序

ItemDefinition
Stateparent、根规模 size、当前组件数 components。
Transitionfind 路径压缩;union 先找根,再把小树根接到大树根。
Frontier / order无搜索前沿;已处理关系被压缩进根结构,未处理操作仍在输入流。

Python 骨架

class DSU:
    def __init__(self, n):
        self.p = list(range(n))
        self.sz = [1] * n
        self.components = n
    def find(self, x):
        while x != self.p[x]:
            self.p[x] = self.p[self.p[x]]
            x = self.p[x]
        return x
    def union(self, a, b):
        a, b = self.find(a), self.find(b)
        if a == b: return False
        if self.sz[a] < self.sz[b]: a, b = b, a
        self.p[b] = a
        self.sz[a] += self.sz[b]
        self.components -= 1
        return True
    def connected(self, a, b):
        return self.find(a) == self.find(b)

正确性思路

  1. 初始每个元素自成集合,不变量成立。
  2. union 只连接不同集合的根,恰好合并两个等价类。
  3. 路径压缩只改挂同树祖先,不改变代表元。
  4. 归纳得 find 相等当且仅当已处理关系使两点连通。

复杂度

TimeSpaceParameters
m 次操作总计 O((n+m) α(n))O(n)n 为对象数,m 为操作数,α 为反 Ackermann 函数

边界条件

错误模式

PatternWhy it fails / fix
直接比较 parentparent 可能尚未压缩,必须比较 find。
合并普通节点必须连接两个根,否则规模和树高失控。
重复合并仍减计数两根相同时应立即返回。

选择与排除规则

相关模板

RelationTemplateBoundary
实现依赖Kruskal 最小生成树判断选边是否成环

原创微型例子

环节内容
Result{0,1,3,4} 成组,2 独立,components=2。
Scenario5 台设备依次接通 0-1、3-4、1-4。
Walkthrough前两次形成两棵树;第三次找到两根并合并,connected(0,3) 变真。

Recall prompts

我的补充