μ°Έκ³ μλ£ : μ΄κ²μ΄ μ½λ© ν μ€νΈλ€ (λλλΉ μ )
1. λ€μν κ·Έλν μκ³ λ¦¬μ¦
\ | κ·Έλν | νΈλ¦¬ |
---|---|---|
λ°©ν₯μ± | λ°©ν₯ κ·Έλν νΉμ 무방ν₯ κ·Έλν | λ°©ν₯ κ·Έλν |
μνμ± | μν λ° λΉμν | λΉμν |
λ£¨νΈ λ Έλ μ‘΄μ¬ μ¬λΆ | λ£¨νΈ λ Έλκ° μμ | λ£¨νΈ λ Έλκ° μ‘΄μ¬ |
λ Έλκ° κ΄κ³μ± | λΆλͺ¨μ μμ κ΄κ³ μμ | λΆλͺ¨μ μμ κ΄κ³ |
λͺ¨λΈμ μ’ λ₯ | λ€νΈμν¬ λͺ¨λΈ | κ³μΈ΅ λͺ¨λΈ |
μλ‘μ μ§ν© (Disjoint Sets)
- μλ‘μ μ§ν© μλ£κ΅¬μ‘° : μλ‘μ λΆλΆ μ§ν©λ€λ‘ λλμ΄μ§ μμλ€μ λ°μ΄ν°λ₯Ό μ²λ¦¬νκΈ° μν μλ£κ΅¬μ‘°
- ν©μ§ν©κ³Ό μ°ΎκΈ° μ°μ°μΌλ‘ ꡬμ±λλ€. =>
union-find
μλ£κ΅¬μ‘° - μλ‘μ μ§ν© μλ£κ΅¬μ‘°λ₯Ό ꡬνν λλ νΈλ¦¬ μλ£κ΅¬μ‘° μ΄μ©
- ν©μ§ν© μ°μ° -> μλ‘ μ°κ²°λ λ λ
Έλ A, B νμΈ
- Aμ Bμ λ£¨νΈ λ Έλ Aβ, Bβλ₯Ό μ°Ύμ
- Aβλ₯Ό Bβμ λΆλͺ¨ λ Έλλ‘ μ€μ
- λͺ¨λ ν©μ§ν© μ°μ°μ μ²λ¦¬ν λκΉμ§ 1λ² λ°λ³΅
κΈ°λ³Έμ μΈ μλ‘μ μ§ν© μκ³ λ¦¬μ¦ μμ€μ½λ
def find_parent(parent, x):
if parent[x] != x:
return find_parent(parent, parent[x])
return x
def union_parent(parent, a, b):
a = find_parent(parent, a)
b = find_parent(parent, b)
if a < b :
parent[b] = a
else :
parent[a] = b
v, e = map(int, input().split())
parent = [0] * (v+1)
for i in range(1, v+1):
parent[i] = i
for i in range(e):
a, b = map(int, input().split())
union_parent(parent, a, b)
print('κ° μμκ° μν μ§ν©: ', end = ' ')
for i in range(1, v+1):
print(find_parent(parent, i), end=' ')
# 1 1 1 1 5 5
- λ¬Έμ μ : find ν¨μμ μκ°λ³΅μ‘λλ
O(V)
κ²½λ‘ μμΆ κΈ°λ²μ μ μ©νμ¬ κ°μ ν μμ€μ½λ
def find_parent(parent, x):
if parent[x] != x: # κ²½λ‘λ¨μΆ
parent[x] = find_parent(parent, parent[x])
return parent[x]
def union_parent(parent, a, b):
a = find_parent(parent, a)
b = find_parent(parent, b)
if a < b :
parent[b] = a
else :
parent[a] = b
v, e = map(int, input().split())
parent = [0] * (v+1)
for i in range(1, v+1):
parent[i] = i
for i in range(e):
a, b = map(int, input().split())
union_parent(parent, a, b)
print('κ° μμκ° μν μ§ν©: ', end = ' ')
for i in range(1, v+1):
print(find_parent(parent, i), end=' ')
μλ‘μ μ§ν© μκ³ λ¦¬μ¦μ μκ° λ³΅μ‘λ
- λ Έλμ κ°μ Vκ°, μ΅λ V-1κ°μ union μ°μ°, Mκ°μ find μ°μ°
- O(V+M(1+log_(2-M/V)V))
μλ‘μ μ§ν©μ νμ©ν μ¬μ΄ν΄ νλ³
- κ° κ°μ μ νμΈνλ©° λ λ
Έλμ λ£¨νΈ λ
Έλλ₯Ό νμΈνλ€.
- λ£¨νΈ λ Έλκ° λ€λ₯΄λ©΄ λ λ Έλμ λν΄ union μ°μ°
- κ°μΌλ©΄ μ¬μ΄ν΄ λ°μ
- λͺ¨λ κ°μ μ λν΄ 1λ² λ°λ³΅
- μ΄ μκ³ λ¦¬μ¦μ κ°μ μ λ°©ν₯μ±μ΄ μλ 무방ν₯ κ·Έλνμμλ§ μ μ© κ°λ₯νλ€.
def find_parent(parent, x):
if parent[x] != x: # κ²½λ‘λ¨μΆ
parent[x] = find_parent(parent, parent[x])
return parent[x]
def union_parent(parent, a, b):
a = find_parent(parent, a)
b = find_parent(parent, b)
if a < b :
parent[b] = a
else :
parent[a] = b
v, e = map(int, input().split())
parent = [0] * (v+1)
for i in range(1, v+1):
parent[i] = i
cycle = False
for i in range(e)
a, b = map(int, input().split())
if find_parent(parent, a) == find_parent(parent, b):
cycle = True
break
else :
union_parent(parent, a, b)
if cycle : print('μ¬μ΄ν΄ λ°μ')
μ μ₯ νΈλ¦¬ (spanning tree)
- μ μ₯ νΈλ¦¬ : νλμ κ·Έλνκ° μμ λ λͺ¨λ λ Έλλ₯Ό ν¬ν¨νλ©΄μ μ¬μ΄ν΄μ΄ μ‘΄μ¬νμ§ μλ λΆλΆ κ·Έλν
- λͺ¨λ λ Έλκ° ν¬ν¨λκ³ μ¬μ΄ν΄μ΄ μ‘΄μ¬νμ§ μμ -> νΈλ¦¬μ μ±λ¦½ 쑰건
ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦
- λνμ μΈ μ΅μ μ μ₯ νΈλ¦¬ μκ³ λ¦¬μ¦
- μ΅μ μ μ₯ νΈλ¦¬ μκ³ λ¦¬μ¦ : μ μ₯ νΈλ¦¬ μ€μμ μ΅μ λΉμ©μΌλ‘ λ§λ€ μ μλ μ μ₯ νΈλ¦¬ μκ³ λ¦¬μ¦
- κ°μ₯ μ μ λΉμ©μΌλ‘ λͺ¨λ λ Έλ μ°κ²°
- 그리λ μκ³ λ¦¬μ¦μΌλ‘ λΆλ₯
- κ°μ λ°μ΄ν°λ₯Ό λΉμ©μ λ°λΌ μ€λ¦μ°¨μ μ λ ¬
- κ°μ μ νλμ© νμΈνλ©° νμ¬ κ°μ μ΄ μ¬μ΄ν΄μ λ°μμν€λμ§ νμΈ
- λ°μνμ§ μμΌλ©΄ μ΅μ μ μ₯ νΈλ¦¬μ ν¬ν¨
- λ°μνλ©΄ ν¬ν¨μν€μ§ μμ
- λͺ¨λ κ°μ μ λν΄ 2λ² λ°λ³΅
- μ΅μ’
μ μΈ μ μ₯ νΈλ¦¬μ ν¬ν¨λλ κ°μ μ κ°μλ
λ Έλμ κ°μ - 1
κ³Ό κ°λ€. - μκ° λ³΅μ‘λ : κ°μ μ κ°μκ° Eκ°μΌ λ,
O(ElogE)
ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦ μ½λ
def find_parent(parent, x):
if parent[x] != x: # κ²½λ‘λ¨μΆ
parent[x] = find_parent(parent, parent[x])
return parent[x]
def union_parent(parent, a, b):
a = find_parent(parent, a)
b = find_parent(parent, b)
if a < b :
parent[b] = a
else :
parent[a] = b
v, e = map(int, input().split())
parent = [0] * (v+1)
edges = []
result = 0
for i in range(1, v+1):
parent[i] = i
for _ in range(e):
a, b, cost = map(int, input().split())
edges.append((cost, a, b))
edges.sort()
for edge in edges:
cost, a, b = edge
if find_parent(parent, a) != find_parent(parent, b):
union_parent(parent, a, b)
result += cost
print(result)
μμμ λ ¬
- μμκ° μ ν΄μ Έ μλ μΌλ ¨μ μμ μ μ°¨λ‘λλ‘ μνν΄μΌ ν λ μ¬μ©ν μ μλ μκ³ λ¦¬μ¦
- μμμ λ ¬μ΄λ, λ°©ν₯ κ·Έλνμ λͺ¨λ λ Έλλ₯Ό λ°©ν₯μ±μ κ±°μ€λ₯΄μ§ μλλ‘ μμλλ‘ λμ΄νλ κ²
- μ§μ μ°¨μ : νΉμ ν λ Έλλ‘ λ€μ΄μ€λ κ°μ μ κ°μ
- μ§μ μ°¨μκ° 0μΈ λ Έλλ₯Ό νμ λ£μ
- νκ° λΉ λκΉμ§ λ€μ κ³Όμ λ°λ³΅
- νμμ μμλ₯Ό κΊΌλ΄ ν΄λΉ λ Έλμμ μΆλ°νλ κ°μ μ κ·Έλνμμ μ κ±°
- μλ‘κ² μ§μ μ°¨μκ° 0μ΄ λ λ Έλλ₯Ό νμ λ£μ
- λͺ¨λ μμλ₯Ό λ°©λ¬ΈνκΈ° μ μ νκ° λΉλ€λ©΄ μ¬μ΄ν΄μ΄ μ‘΄μ¬νλ κ²
- λ€λ§ κΈ°λ³Έμ μΌλ‘ μμ μ λ ¬ λ¬Έμ μμλ μ¬μ΄ν΄μ΄ λ°μνμ§ μλλ€κ³ λͺ μνλ κ²½μ°κ° λ λ§μ
- μκ° λ³΅μ‘λ :
O(V+E)
from collections import deque
v, e = map(int, input().split())
indegree = [0] * v+1
graph = [[] for i in range(v+1)]
for _ in range(e) :
a, b = map(int, input().split())
graph[a].append(b)
indegree[b] += 1
def topology_sort():
result = [] # μκ³ λ¦¬μ¦ μν κ²°κ³Ό
q = deque()
for i in range(1, v+1) :
if indegree[i] == 0 : q.append(i)
while q :
now = q.popleft()
result.append(now)
for i in graph[now]:
indegree[i] -= 1
if indegree[i] == 0 :
q.append(i)
for i in result:
print(i, end=' ')
topology_sort()