[Algorithm] Graph Theory
π£
λ³Έ ν¬μ€νΈλ βμ΄κ²μ΄ μ·¨μ
μ μν μ½λ© ν
μ€νΈλ€ with νμ΄μ¬βμ 곡λΆνκ³ μμ±νμμ΅λλ€ :)
click > (μ΄μ½ν
2021) μ΄κ²μ΄ μ·¨μ
μ μν μ½λ© ν
μ€νΈλ€ with νμ΄μ¬
Graph Theory
μ΄λ‘
μμ λ°°μ΄ DFS/BFSμ μ΅λ¨ κ²½λ‘μμ λ€λ£¬ λ΄μ©λ€ λͺ¨λ κ·Έλν μκ³ λ¦¬μ¦μ ν μ νμ΄λ€. κ·Έ μΈμλ λ€μν κ·Έλν μκ³ λ¦¬μ¦μ΄ μλλ°, μ΄ μ₯μμλ κ·Έ μ€μμ λͺ κ°μ§λ₯Ό μΆκ°μ μΌλ‘ λ°°μ΄λ€.
μλ‘μ μ§ν© (Disjoint Sets)
κ³΅ν΅ μμκ° μλ λ μ§ν©μ μλ―Ένλ€.
μλ‘μ μ§ν© μλ£κ΅¬μ‘°
μλ‘μ λΆλΆ μ§ν©λ€λ‘ λλμ΄μ§ μμλ€μ λ°μ΄ν°λ₯Ό μ²λ¦¬νκΈ° μν μλ£κ΅¬μ‘°λ‘ unionκ³Ό find 2κ°μ μ°μ°μΌλ‘ μ‘°μν μ μλ€. μ§ν©μ νΈλ¦¬ μλ£κ΅¬μ‘°λ₯Ό μ΄μ©νμ¬ νννλ€.
- union μ°μ° : 2κ°μ μμκ° ν¬ν¨λ μ§ν©μ νλμ μ§ν©μΌλ‘ ν©μΉλ μ°μ°μ΄λ€.
- find μ°μ° : νΉμ ν μμκ° μν μ§ν©μ΄ μ΄λ€ μ§ν©μΈμ§ μλ €μ£Όλ μ°μ°μ΄λ€.
μλ‘μ μ§ν© κ³μ° μκ³ λ¦¬μ¦
- union μ°μ°μ νμΈνλ©°, μλ‘ μ°κ²°λ λ λ
Έλ A, Bλ₯Ό νμΈνλ€.
- Aμ Bμ λ£¨νΈ λ Έλλ₯Ό κ°κ° μ°Ύλλ€.
- Aμ λ£¨νΈ λ Έλλ₯Ό Bμ λ£¨νΈ λ Έλλ‘ μ€μ νλ€. (λ μμ λ£¨νΈ λ Έλλ₯Ό κ°λ¦¬ν€λλ‘ νλ€. )
- λͺ¨λ 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, a)
if a < b:
parent[b] = a
else :
parent[a] = b
# λ
Έλμ κ°μμ κ°μ (union μ°μ°)μ κ°μ μ
λ ₯λ°κΈ°
v, e = map(int, input(),split())
parent = [0] * (v+1) # λΆλͺ¨ ν
μ΄λΈ μ΄κΈ°ν
# λΆλͺ¨ ν
μ΄λΈμμμ, λΆλͺ¨λ₯Ό μκΈ° μμ μΌλ‘ μ΄κΈ°ν
for i in range(1, v+1):
parent[i] = i
# union μ°μ°μ κ°κ° μν
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=" ")
print()
# λΆλͺ¨ ν
μ΄λΈ λ΄μ© μΆλ ₯
print("λΆλͺ¨ ν
μ΄λΈ: " end="")
for i in range(1, v+1):
print(parent[i], end=" ")
μλ‘μ μ§ν© μκ³ λ¦¬μ¦μ μκ° λ³΅μ‘λ
λ Έλμ κ°μκ° Vκ°κ³ μ΅λ V-1 κ°μ union μ°μ°κ³Ό Mκ°μ findμ°μ°μ΄ κ°λ₯ν λ κ²½λ‘ μμΆ λ°©λ²μ μ μ©ν μκ° λ³΅μ‘λλ $O(V + M(1 + M(1 + log_{1-M/V}V))$ μ΄λ€.
μλ‘μ μ§ν©μ νμ©ν μ¬μ΄ν΄ νλ³
μλ‘μ μ§ν©μ λ€μν μκ³ λ¦¬μ¦μ μ¬μ©ν μ μλλ°, νΉν μλ‘μ μ§ν©μ 무방ν₯ κ·Έλν λ΄μμμ μ¬μ΄ν΄μ νλ³ν λ μ¬μ©ν μ μλ€. (λ°©ν₯ κ·Έλνμμμ μ¬μ΄ν΄ μ¬λΆλ DFSλ‘ νλ³)
- κ° κ°μ μ νμΈνλ©° μ°κ²°λ λ λ
Έλμ λ£¨νΈ λ
Έλλ₯Ό νμΈνλ€.
- λ£¨νΈ λ Έλκ° μλ‘ λ€λ₯΄λ€λ©΄ λ λ Έλμ λνμ¬ union μ°μ°μ μννλ€.
- λ£¨νΈ λ Έλκ° μλ‘ κ°λ€λ©΄ μ¬μ΄ν΄μ΄ λ°μν κ²μ΄λ€.
- κ·Έλνμ ν¬ν¨λμ΄ μλ λͺ¨λ κ°μ μ λνμ¬ 1λ² κ³Όμ μ λ°λ³΅νλ€.
μ μ₯ νΈλ¦¬
μ μ₯ νΈλ¦¬ (Spanning Tree)λ νλμ κ·Έλνκ° μμ λ, λͺ¨λ λ Έλλ₯Ό ν¬ν¨νλ©΄μ μ¬μ΄ν΄μ΄ μ‘΄μ¬νμ§ μλ λΆλΆ κ·Έλνλ₯Ό μλ―Ένλ€. μ΄ λ, λͺ¨λ λ Έλκ° ν¬ν¨λμ΄ μλ‘ μ°κ²°λλ©΄μ μ¬μ΄ν΄μ΄ μ‘΄μ¬νμ§ μλλ€λ 쑰건μ νΈλ¦¬μ μ±λ¦½ 쑰건μ΄κΈ°λ νλ€.
ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦
μ μ₯ νΈλ¦¬ μ€μμ μ΅μ λΉμ©μΌλ‘ λ§λ€ μ μλ μ μ₯ νΈλ¦¬λ₯Ό μ°Ύλ μκ³ λ¦¬μ¦μ βμ΅μ μ μ₯ νΈλ¦¬ μκ³ λ¦¬μ¦βμ΄λΌκ³ νλ€. λνμ μΈ μ μ₯ νΈλ¦¬ μκ³ λ¦¬μ¦μΌλ‘ ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦μ΄ μλ€.
ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦μ μ¬μ©νλ©΄ κ°μ₯ μ μΈ λΉμ©μΌλ‘ λͺ¨λ λ Έλλ₯Ό μ°κ²°ν μ μλ€.
- κ°μ λ°μ΄ν°λ₯Ό λΉμ©μ λ°λΌ μ€λ¦μ°¨μμΌλ‘ μ λ ¬νλ€.
- κ°μ μ νλμ© νμΈνλ©° νμ¬μ κ°μ μ΄ μ¬μ΄ν΄μ λ°μμν€λμ§ νμΈνλ€.
- μ¬μ΄ν΄μ΄ λ°μνμ§ μλ κ²½μ°, μ΅μ μ μ₯ νΈλ¦¬μ ν¬ν¨μν¨λ€.
- μ¬μ΄ν΄μ λ°μνλ κ²½μ°, μ΅μ μ μ₯ νΈλ¦¬μ ν¬ν¨μν€μ§ μλλ€.
- λͺ¨λ κ°μ μ λνμ¬ 2λ² κ³Όμ μ λ°λ³΅νλ€.
ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦ μμ€μ½λ
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())
edges = [list(map(int, input().split())) for _ in range(e)]
parent = [i for i in range(v+1)]
edges.sort(key=lambda x:x[2])
result = 0
for edge in edges:
a,b,cost = edge
if find_parent(parent,a) != find_parent(parent,b):
union_parent(parent,a,b)
result+=cost
print(result)
ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦μ μκ°λ³΅μ‘λ
ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦μ κ°μ μ κ°μκ° EμΌ λ, O(ElogE)μ μκ° λ³΅μ‘λλ₯Ό κ°μ§λ€.
μμμ λ ¬ μκ³ λ¦¬μ¦
μμ μ λ ¬ (Topology Sort)λ μ λ ¬ μκ³ λ¦¬μ¦μ μΌμ’ μΌλ‘, μμκ° μ ν΄μ Έ μλ μ΄λ ¨μ μμ μ μμλλ‘ μνν΄μΌ ν λ μ¬μ©ν μ μλ μκ³ λ¦¬μ¦μ΄λ€. μ¦, λ°©ν₯ κ·Έλνμ λͺ¨λ λ Έλλ₯Ό λ°©ν₯μ±μ κ±°μ€λ₯΄μ§ μλλ‘ μμλλ‘ λμ΄νλ κ²μ΄λ€.
μ§μ μ°¨μ(indegree) : νΉμ ν λ Έλλ‘ λ€μ΄μ€λ κ°μ μ κ°μμ΄λ€.
- μ§μ μ°¨μκ° 0μΈ λ Έλλ₯Ό νμ λ£λλ€.
- νκ° λΉ λκΉμ§ λ€μμ κ³Όμ μ λ°λ³΅νλ€.
- νμμ μμλ₯Ό κΊΌλ΄ ν΄λΉ λ Έλμμ μΆλ°νλ κ°μ μ κ·Έλνμμ μ κ±°νλ€.
- μλ‘κ² μ§μ μ°¨μκ° 0μ΄λ λ Έλλ₯Ό νμ λ£λλ€.
v, e = map(int, input().split())
indegree = [0] * (v + 1)
graph = [[] for i in range(v + 1)]
answer = [1] * (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)
topology_sort()
for i in result():
print(i, end='')
μμμ λ ¬μ μκ° λ³΅μ‘λ
μ°¨λ‘λλ‘ λͺ¨λ λ Έλλ₯Ό νμΈνλ©΄μ, ν΄λΉ λ Έλμμ μΆλ°νλ κ°μ μ μ°¨λ‘λλ‘ μ κ±°ν΄μΌ νλ€. λ°λΌμ μμ μ λ ¬μ μκ° λ³΅μ‘λλ O(V + E)μ΄λ€.
κΈ°μΆ λ¬Έμ
[Baekjoon 1647] λμλΆν κ³ν
import sys
input = sys.stdin.readline
# νΉμ μμκ° μν μ§ν©μ μ°ΎκΈ°
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() # λΉμ© μμΌλ‘ μ λ ¬
max_edge = 0 # μ΅μ μ μ₯ νΈλ¦¬μ ν¬ν¨λλ κ°μ μ€μμ κ°μ₯ λΉμ©μ΄ ν° κ°μ
for edge in edges:
cost,a,b = edge
# μ¬μ΄ν΄μ΄ λ°μνμ§ μλ κ²½μ°
if find_parent(parent,a) != find_parent(parent,b):
union_parent(parent,a,b)
result += cost
max_edge = cost
print(result - max_edge)
[Baekjoon 14567] μ μκ³Όλͺ©
from collections import deque
import sys
input = sys.stdin.readline
v, e = map(int, input().split())
indegree = [0] * (v + 1)
graph = [[] for i in range(v + 1)]
answer = [1] * (v + 1)
for _ in range(e):
a, b = map(int, input().split())
graph[a].append(b)
indegree[b] += 1
def topology_sort():
q = deque()
for i in range(1, v + 1):
if indegree[i] == 0:
q.append(i)
while q:
now = q.popleft()
flag = False
for i in graph[now]:
indegree[i] -= 1
if indegree[i] == 0:
q.append(i)
answer[i] = answer[now] + 1
topology_sort()
for x in answer[1:]:
print(x, end=" ")
λκΈλ¨κΈ°κΈ°