並差集-python版本

並差集-python版本

簡介

並查集,在一些有N個元素的集合應用問題中,我們通常是在開始時讓每個元素構成一個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查找一個元素在哪個集合中。 --百度百科

應用

一些常見的用途有求連通子圖、求最小生成樹的 Kruskal 算法和求最近公共祖先(Least Common Ancestors, LCA)等。

基本操作

初始化

並查集的實現原理也比較簡單,就是使用樹來表示集合,樹的每個節點就表示集合中的一個元素,樹根對應的元素就是該集合的代表

dsu示意圖

圖中有兩棵樹,分別對應兩個集合,其中第一個集合爲$ {a,b,c,d}$,代表元素是 aa;第二個集合爲 {e,f,g}\{e,f,g\},代表元素是 ee

樹的節點表示集合中的元素,指針表示指向父節點的指針,根節點的指針指向自己,表示其沒有父節點。沿着每個節點的父節點不斷向上查找,最終就可以找到該樹的根節點,即該集合的代表元素。

# parent數組記錄該元素父節點的序號,size表示該樹高(以根節點計算)
class DSU:
    def __init__(self, num):
        self.parent = list(range(num))
        self.size = [1] * num

查找根節點

通過遞歸的方式,進行查找該樹的根節點。如:find(d) -> a.

查找根節點

    def find(self, x):
        '''
        查找x的父節點
        :param x:
        :return:
        '''
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

求並集

在並集的時候,通過size數組記錄樹高,從而進行路徑壓縮。可以防止極端情況,如查找中的圖。

交集

    def union(self, x, y):
        '''
        合併x和y的集合
        :param x:
        :param y:
        :return:
        '''
        x_root = self.find(x)
        y_root = self.find(y)
        if x_root == y_root:
            return
        # 根據樹高進行計算
        if self.size[x_root] > self.size[y_root]:
            # 將y合併到x
            self.parent[y_root] = x_root
        elif self.size[x_root] < self.size[y_root]:
            self.parent[x_root] = y_root
        else:
            self.parent[x_root] = y_root  # x拼接到y上
            self.size[y_root] = self.size[y_root] + 1

參考

【算法】並查集(Disjoint Set)

並查集

924. Minimize Malware Spread

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章