UnionFind:快查连通图

并查集UnionFind又叫Disjoint Sets。它的作用是快速更新和查询节点的连通性。

数组简单实现

简单的并查集实现如下:用数组表示祖节点。

主要功能:

  • find(p):O(N)找到p所在连通图的根 实现:不断向父节点查找

  • union(p, q):(N)把p和q连通 实现:把含有p的根接到含有q的根上

  • connected(p, q):O(N)判断p和q是否连通 实现:判断含有p和q的数是否有一样的根节点

  • self.count:O(1)得到连通图的个数

class UF:
    def __init__(self, n):
        self.parent = [x for x in range(n)]
        self.count = n

    def find(self, p):
        while self.parent[p]!=p:
            p = self.parent[p]
        return p

    def union(self, p, q):
        rootp, rootq = self.find(p), self.find(q)
        if rootp==rootq: return
        self.parent[rootp] = rootq
        self.count -= 1
        
    def connected(self, p, q):
        return self.find(p)==self.find(q)

并查集让一些图的查询和改动变得很方便。比如说我们可以用O(1)的时间查询有几个连通量。在处理很多数据(或者数据流)的时候,能让我们快速知道图的连通性。在《图的性质》章节,我们会细看图的连通性。

路径压缩 / 小树接大树

在这里可以有一些优化:在union过程中加入平衡考虑(小树接大树),以及在find过程中顺便加入路径压缩,可以让查找和union更快。具体可以参考此文。这样一来,findunionconnected的时间复杂度都降到了O(logN)。

带权重的UnionFind

目前的UnionFind是一个无向的多叉树。有时候要求不仅能求连通性,而且要计算节点之间的连接的权重。这个时候就需要一个带权重的UnionFind,成为一个无环有向图。

下面的参考代码在“查询“操作的“路径压缩“优化中维护权值变化。

例题:快速除法

Last updated

Was this helpful?