ποΈ Graph Theory 4: Union-Find (Disjoint Set)
π
Β Disjoint Set
μλ‘ κ³΅ν΅λ μμλ₯Ό κ°μ§κ³ μμ§ μμ μ¬λ¬ μ§ν©λ€μ μ§μΉνλ μ©μ΄λ€. κ°λ³ μμκ° μ νν νλμ μ§ν©μ μνλ©°, μ΄λ€ μ§ν©λ μλ‘ κ³΅ν΅ μμλ₯Ό κ°μ§κ³ μμ§ μμμΌ νλ€. μλ‘μ μ§ν© μλ£κ΅¬μ‘°λ₯Ό μ¬μ©νλ©΄ μλ‘ λ€λ₯Έ μμλ€μ΄ κ°μ μ§ν©κ΅°μ μν΄ μλκ° νλ³νλ κ²κ³Ό κ°μ μμ
μ μ½κ² ν μ μλ€. κ·Έλ λ€λ©΄ μ΄μ λΆν° μλ£κ΅¬μ‘°λ‘μ μλ‘μ μ§ν©μ ν¨κ³Όμ μΌλ‘ νννκ³ μ‘°μν μ μλ Makeset
, Union
, Find
μ°μ°μ λν΄μ μμ보μ.
ποΈΒ Makeset
νΈλ¦¬ μλ£κ΅¬μ‘°λ₯Ό νμ©ν΄ μ§ν©μ νννλ λ°©λ² μ€ νλλ‘, μ£Όμ΄μ§ μμλ§ μ€λ³΅μμ΄ ν¬ν¨νλ μ§ν©μ μμ±νλ μ°μ°μ΄λ€. μ€μ μ½λμ ꡬνμΌλ‘λ λ°°μ΄, 리μ€νΈ μλ£κ΅¬μ‘°λ₯Ό νμ©νλ€. λ°°μ΄μ μΈλ±μ€λ₯Ό κ°λ³ μμμ μλ³μλ‘ κ°μ£Όνκ³ ν΄λΉ μμΉμ κ°μλ λΆλͺ¨ μμμ μΈλ±μ€λ₯Ό μ±μ λ£λλ€. λ§μ½ μΈλ±μ€μ μμκ°μ΄ λμΌνλ€λ©΄ ν΄λΉ μμκ° ν¬ν¨λ μ§ν©μμ νμ¬ μμκ° λ£¨νΈ λ Έλμμ μλ―Ένλ€. μ΄λ κ² νΉμ μΈλ±μ€μ μμκ°μ νκ³ κ±°μ¬λ¬ μ¬λΌκ°λ€λ©΄ λ§λκ² λλ λ£¨νΈ λ Έλμ κ°μ μ΄μ©ν΄ μ°λ¦¬λ μλ‘ λ€λ₯Έ λ μμκ° κ°μ μ§ν©μ μνλμ§ νΉμ λ€λ₯Έ μ§ν©μ μνλμ§ κ΅¬λ³ν μ μκ² λλ€.
""" Disjoint Makeset Example """
N = int(sys.stdin.readline()) # λ
Έλ κ°μ
M = int(sys.stdin.readline()) # μ£μ§ κ°μ
parent = [0]*(N+1)
# 1) Makeset Array Init
for i in range(1, N+1):
parent[i] = i
λ°°μ΄μ μΈλ±μ€λ₯Ό κ°λ³ λ
Έλμ μλ³μλ‘ μ¬μ©νκΈ° μν΄, μ 체 κ·Έλν μμ λ
Έλ κ°μλ§νΌ λ°°μ΄μ ν¬κΈ°λ₯Ό μ΄κΈ°ν ν΄μ£Όκ³ μλ€. κ·Έλ¦¬κ³ μ΄κΈ°μλ μμ§ λ
Έλ μ¬μ΄μ μ°κ²° μ 보μ λν΄μ μ£Όμ΄μ§κ² μ ν μκΈ° λλ¬Έμ κ°λ³ λ
Έλ μμ μ΄ λ£¨νΈ λ
Έλκ° λλλ‘ μ΄κΈ°νλ₯Ό ν΄μ£Όλκ² μΌλ°μ μ΄λ€. μ΄λ κ² μ΄κΈ°νν λ°°μ΄μ Union
, Find
μ°μ°μ νμ©λλ€.
π¬Β Find
μ΄λ€ μμκ° μν μ§ν©μ λ£¨νΈ λ
Έλ κ°μ λ°ννλ μ°μ°μ΄λ€. Find
μ°μ°μ μμ μ΄κΈ°νν Makeset Array
λ₯Ό ν΄λΉ μ§ν©(νΈλ¦¬)μ λ£¨νΈ λ
Έλλ₯Ό λ§λ λκΉμ§ μ¬κ·μ μΌλ‘ μννλ€. μ€μ λ‘λ λ¨μ λ£¨νΈ λ
Έλλ₯Ό λ°ννλ μ©λλ‘ μ¬μ©νμ§ μκ³ , νΉμ λ μμκ° κ°μ μ§ν©(νΈλ¦¬)μ μνλμ§ μλλ©΄ μλ‘ λ€λ₯Έ μ§ν©μ μνλμ§ νμ νλλ° μ¬μ©λλ€. μλ‘ λ€λ₯Έ λ μμλ₯Ό Find
μ°μ°μμ λ£μ΄μ£Όλ©΄ κ°κ°μ λ£¨νΈ λ
Έλλ₯Ό ꡬν μ μλλ°, μ΄ λ μλ‘ κ°μ λ£¨νΈ λ
Έλκ°μ λ°ννλ€λ©΄ κ°μ μ§ν©μ΄λΌκ³ κ°μ£Όνκ³ λ€λ₯΄λ€λ©΄ μλ‘ μλ‘μ κ΄κ³μ μλ€κ³ νλ¨ν μ μλ€.
""" find method """
def find(arr: list, x: int) -> int:
""" method for finding root node """
if arr[x] != x:
arr[x] = find(arr, arr[x])
return arr[x]
# 1) Kruskal Algorithm
result = 0
for j in range(M):
weight, start, final = graph[j]
if find(parent, start) != find(parent, final):
union(parent, start, final)
result += weight
μ μμ€μ½λμ²λΌ Kruskal
Algorithmμ²λΌ μ΅μ μ€ν¨λ νΈλ¦¬κ° νμν μν©μ μμ£Ό μ¬μ©λλ€. λν κ·Όλ³Έμ΄ νΈλ¦¬ μλ£κ΅¬μ‘°μ λν μ°μ°μ΄λΌλ μ μ νμ©ν΄, νΉμ κ·Έλνμ μ¬μ΄ν΄ μ¬λΆλ₯Ό νμ νλ μκ³ λ¦¬μ¦μΌλ‘λ λ§μ΄ μ¬μ©λκ³ μλ€.
π©βπ©βπ§βπ¦Β Union
λ κ°μ μ§ν©μ νλλ‘ ν©μΉλ μ°μ°μ΄λ€. μ§ν©μ λ£¨νΈ λ
Έλλ₯Ό λ€λ₯Έ μ§ν©μ λ£¨νΈ λ
Έλ μλμ μ°κ²°νλ λ°©μμΌλ‘ ν©μΉλ€. ν©μΉλ λ°©μμλ λ€μν λ°©λ²λ‘ μ΄ μ‘΄μ¬νλλ°, μΌλ°μ μΌλ‘ λ£¨νΈ λ
Έλμ λ²νΈκ° λ μμ μͺ½μ λ ν° μͺ½μ μ§ν©(νΈλ¦¬)λ₯Ό λΆμ¬μ£Όλ Union by Rank
λ°©μμ λ§μ΄ μ¬μ©νλ€.
""" union method """
def union(arr: list, x: int, y: int):
""" method for union-find """
x = find(arr, x)
y = find(arr, y)
if x < y:
arr[y] = x
else:
arr[x] = y
# 1) Kruskal Algorithm
result = 0
for j in range(M):
weight, start, final = graph[j]
if find(parent, start) != find(parent, final):
union(parent, start, final)
result += weight
print(result)
μμ λ§μ°¬κ°μ§λ‘ μ΅μ μ€ν¨λ νΈλ¦¬κ° νμν μν©μ μμ£Ό μ¬μ©λκ³ μμΌλ©°, μ£Όλ‘ Findλ₯Ό ν΅ν΄ μλ‘μ μ§ν© κ΄κ³μ λμΈ μ§ν©λ€μ νμ νκ³ , κ·Έλ€μ νλλ‘ ν΅ν©μν€λλ° μμ£Ό μ°μΈλ€.
Leave a comment