0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

素敵なデータ構造:Union-Find木 by Python

Last updated at Posted at 2021-05-15

データ構造の説明

Union-Find木とは、
・根付き木の構造を用いて
・グループ分けを効率的に管理するデータ構造
なようです。

UnionFind.py
class UnionFind():
    par = []
    siz = []
    
    def __init__(self, x):
        self.par = [-1 for n in range(x)]
        self.siz = [1 for n in range(x)]
    
    def root(self, x):
        if self.par[x] == -1:
            return x
        else:
            self.par[x] = self.root(self.par[x])
            return self.par[x]
    
    def issame(self, x, y):
        if self.root(x) == self.root(y):
            return True
        else:
            return False
    
    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.siz[x] < self.siz[y]:
            x, y = y, x
        self.par[y] = x
        self.siz[x] += self.siz[y]
        return True
    
    def size(self, x):
        return self.siz[self.root(x)]
        
uf = UnionFind(7)
uf.unite(2, 3)
uf.issame(2, 3)

# 出力 True

アルゴリズムへの適用

連結成分個数カウント

CountConnectedComponent.py
# アルゴリズム定義
# Union-Find木を用いた連結成分個数カウント
def CountConnectedComponent(uf, N):
    res = 0
    for i in range(N):
        if uf.root(i) == i:
            res += 1

    print(res)

# 入力受取
# 頂点数、辺数
N, M = map(int, input().split())

# Union-Find木の生成
# Nで初期化
uf = UnionFind(N)

# グラフの生成
# 各辺の情報をUnion-Find木に追加
for i in range(M):
    a, b = map(int, input().split())
    uf.unite(a, b)

# アルゴリズム実行
# Union-Find木を用いた連結成分個数カウント
CountConnectedComponent(uf, N)

# 入力
# 13 14
# 0 1
# 0 2
# 0 3
# 1 4
# 2 4
# 3 5
# 2 6
# 6 7
# 5 8
# 7 8
# 10 11
# 11 12
# 4 5
# 1 6

# 出力
# 3

クラスカル法

Kruskal.py
# アルゴリズム定義
# クラスカル法
def Kruskal(N, M):
    res = 0    
    uf = UnionFind(N)
    for i in range(M):
        w = edges[i][0]
        u = edges[i][1][0]
        v = edges[i][1][1]

        if uf.issame(u, v):
            continue

        res += w
        uf.unite(u, v)

    print(res)

# 入力受取
# 頂点数、辺数
N, M = map(int, input().split())

# グラフの生成
# 辺(u,v)と重みwの集合
edges = ["" for i in range(M)]
for i in range(M):
    u, v, w = map(int, input().split())
    edges[i] = [w, [u, v]]

# グラフの並び替え
# 重みの小さい順に並び替え
edges.sort()

# アルゴリズム実行
# クラスカル法
Kruskal(N, M)

# 入力
# 4 6
# 0 1 10
# 1 2 20
# 2 3 30
# 3 0 40
# 1 3 15
# 0 2 45

# 出力
# 45
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?