MST(Minimum Spanning Tree)๋ ๊ฐ์ค์น๊ฐ ์๋ ๋ฌด๋ฐฉํฅ ๊ทธ๋ํ์์ ์ต์ ๋น์ฉ์ผ๋ก ๋ชจ๋ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํ๋ ํธ๋ฆฌ๋ฅผ ๋งํ๋ค. โํธ๋ฆฌโ๋ผ๊ณ ํ๋ ์ด์ ๋ ์ด ๊ทธ๋ํ์ cycle์ด ์์ด์ผํ๊ธฐ ๋๋ฌธ์ด๋ค.
MST๋ฅผ ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋ํ์ ์ผ๋ก ๋๊ฐ์ง๊ฐ ์๋ค.
๋ฐ๋ก ํฌ๋ฃจ์ค์นผ(Kruskal) ์๊ณ ๋ฆฌ์ฆ๊ณผ ํ๋ฆผ(Prim) ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
๋์ ํ๋ฆ๊ณผ ํต์ฌ ๊ฐ๋ , ๊ทธ๋ฆฌ๊ณ ๊ตฌํ๊น์ง ์์๋ณด์!
ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ์ ์ ์ค์ฌ์ผ๋ก ํ๋ MST ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
๋๋ต์ ์ผ๋ก ์ดํด๋ณด๋ ํ๋ฆ์ ์ด๋ ๋ค.
์ ๋ ฌ์ด ์ ์ฒด ์๊ฐ๋ณต์ก๋๋ฅผ ์ง๋ฐฐํ๋ฏ๋ก ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ์ ์๊ฐ๋ณต์ก๋๋ O(E log E)๊ฐ ๋๋ค.
์์ ๋จ๊ณ๋ค์ ํ๋ํ๋ ์ดํด๋ณด์.
์ผ๋จ ๊ฐ์ ์ (๊ฐ์ค์น, ๋
ธ๋A, ๋
ธ๋B)
์ ๊ฐ์ด ๋ํ๋์ ๋, ์์ ๊ฐ์ด ์ ๋ ฌํ ์ ์๋ค.
์ฒซ๋ฒ์งธ ๊ฐ์ ์ ๋
ธ๋ 1๊ณผ 2๋ฅผ ๊ฐ์ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด์ค๋ค. ์ฆ, ์ ํ๋(ํ๋์์ผ๋ก ์น ํด์ง) ์ ์ ์ด ์ ํ๋ ๊ทธ๋ฃน์ ์๋ ์ ์ ์ด ๋๋ค.
๊ฐ์ ์ ์ ํํ ๋ ์ด๋ฏธ ๋ ์ ์ ๋ชจ๋ ์ ํ๋ ๊ทธ๋ฃน์ ์ํด์๋ค๋ฉด ์ฌ์ดํด์ ํ์ฑํ๋ ๊ฒ์ผ๋ก ๊ฑธ๋ฌ๋ผ ์ ์๋ค.
ํด๋น ๊ฐ์ ์ ์ ์ฌ์ดํด์ ํ์ฑํ์ง ์์ผ๋ฏ๋ก ์ ํํ๊ณ ๋ค์์ผ๋ก ๋์ด๊ฐ๋ค.
๋๋ฒ์งธ ๊ฐ์ ์ ์ ํํ์ ๋ 3์ด ์ ํ๋์ง ์์ ๊ทธ๋ฃน์ ์ ์ ์ด๋ฏ๋ก ์ฌ์ดํด ํ์ฑ์ด ๋์ง ์๊ณ ,
๋๋ฒ์งธ ๊ฐ์ ๋ํ ์ ํํ๊ณ ๋์ด๊ฐ๋ค.
์ธ๋ฒ์งธ ๊ฐ์ ์ ์ ํํ์ ๋ 4๊ฐ ์ ํ๋์ง ์์ ๊ทธ๋ฃน์ ์ ์ ์ด๋ฏ๋ก ์ฌ์ดํด์ด ํ์ฑ๋์ง ์๊ณ ,
์ ํํ๊ณ ๋์ด๊ฐ๋ค.
๋ค๋ฒ์งธ ๊ฐ์ ์ ์ ํํ์ ๋ 0์ด ์ ํ๋์ง ์์ ๊ทธ๋ฃน์ ์ ์ ์ด๋ฏ๋ก ์ฌ์ดํด์ด ํ์ฑ๋์ง ์๊ณ ,
์ ํํ๊ณ ๋์ด๊ฐ๋ค.
๋ค์ฏ๋ฒ์งธ ๊ฐ์ ์ ์ ํํ์ ๋ 1๊ณผ 0 ๋ชจ๋ ์ ํ๋ ๊ทธ๋ฃน์ ์ ์ ์ด๋ฏ๋ก ์ฌ์ดํด์ด ํ์ฑ๋์ด,
์ ํํ์ง ์๊ณ ๋์ด๊ฐ๋ค.
์ฌ์ฏ๋ฒ์งธ ๊ฐ์ ์ ์ ํํ์ ๋๋ 2์ 3 ๋ชจ๋ ์ ํ๋ ๊ทธ๋ฃน์ ์ ์ ์ด๋ฏ๋ก ์ฌ์ดํด์ด ํ์ฑ๋์ด,
์ ํํ์ง ์๊ณ ๋์ด๊ฐ๋ค.
๋ง์ง๋ง์ผ๋ก ์ผ๊ณฑ๋ฒ์งธ ๊ฐ์ ์ ์ ํํ์ ๋ 5๊ฐ ์ ํ๋์ง ์์ ๊ทธ๋ฃน์ ์ ์ ์ด๋ฏ๋ก ์ฌ์ดํด์ด ํ์ฑ๋์ง ์๊ณ ,
์ ํํ๊ณ ๋ง๋ฌด๋ฆฌํ๋ค.
### Kruskal
# union-find
def find_non_recursion(parent, x):
while parent[x] != x:
parent[x] = parent[parent[x]] # ๊ฒฝ๋ก ์์ถ
x = parent[x]
return x
def find_recursion(parent, x):
if parent[x] != x:
parent[x] = find_recursion(parent, parent[x]) # ๊ฒฝ๋ก ์์ถ
return parent[x]
def union(parent, x, y):
x_root = find(parent, x)
y_root = find(parent, y)
if x_root == y_root:
return False
parent[y_root] = x_root
return True
# kruskal
def kruskal(v, graph):
parent = [i for i in range(v+1)]
graph.sort(key=lambda x: x[2])
result = 0
for a, b, weight in graph:
if union(parent, a, b):
result += weight
return result
if __name__ == "__main__":
v = 6
inp = [(
graph = [(1, 1, 2), (2, 1, 3), (2, 3, 4), (3, 2, 0), (4, 0, 1), (4, 2, 3), (6, 4, 5)]
answer = kruskal(graph)
print(answer)
ํ๋ฆผ ์๊ณ ๋ฆฌ์ฆ์ ์ ์ ์ ์ค์ฌ์ผ๋ก ํ๋ MST ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
๋๋ต์ ์ธ ํ๋ฆ์ ์๋์ ๊ฐ๋ค.
(weight, node)
ํ์์ผ๋ก ์ฝ์
ํ๋ค.ํ ๋ ธ๋์ ์ต๋๋ก ๋ค์ด๊ฐ ์ ์๋ ๊ฐ์ ์ ์๋ ์ ์ฒด ๊ฐ์ ์ ์์ธ E์ด๊ณ , ์ฐ์ ์์ ํ๋ฅผ ์ด์ฉํด ์ฝ์ ๊ณผ ์ญ์ ๋ฅผ ๊ตฌํํ์ ๋ ์ฝ์ , ์ญ์ ์ ์์๋๋ ์๊ฐ์ ์ต๋ log V์ด๋ฏ๋ก ์ ์ฒด ์๊ฐ๋ณต์ก๋๋ O(E log V)์ด๋ค.
์ ๋จ๊ณ๋ค์ ์ฐจ๋ก๋ก ์ดํด๋ณด์.
์ด๊ธฐ ๋
ธ๋๋ฅผ 0์ผ๋ก ์ค์ ํ๊ณ , 0์ pq์ ์ฝ์
ํ ๋ค ์์ํ๋ค. ์ด๋ ๊ฐ์ค์น๋ 0์ผ๋ก ์ค์ ํ๋ค.
pq์์ popํ๋ฉด ์ด๊ธฐ๊ฐ์ธ (0, 0)์ด ๋์ค๊ณ , ์ด๊ธฐ์๋ ์ด๋ค ์ ์ ๋ ๋ฐฉ๋ฌธ์ฒ๋ฆฌ(์ด๋ก์) ๋์ง ์์์ผ๋ฏ๋ก 0์ ์ ํํ๋ค.
๊ทธ๋ฆฌ๊ณ 0๊ณผ ์ฐ๊ฒฐ๋ ์ ์ ์ธ 1, 2 ๋ชจ๋ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ด๋ฏ๋ก pq์ pushํ๋ค.
pq์์ popํ๋ฉด (3, 2)๊ฐ ๋์ค๊ณ , 2๋ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ด๋ฏ๋ก ์ ํํ๊ณ ๋ฐฉ๋ฌธ์ฒ๋ฆฌํ๋ค.
2์ ์ฐ๊ฒฐ๋ 0, 1, 3 ์ค์์ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ธ 1, 3์ pq์ pushํ๋ค.
pq์์ popํ๋ฉด (1, 1)์ด ๋์ค๊ณ , 1์ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ด๋ฏ๋ก ์ ํํ๊ณ ๋ฐฉ๋ฌธ์ฒ๋ฆฌํ๋ค.
1๊ณผ ์ฐ๊ฒฐ๋ 0, 2, 3 ์ค์์ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ธ 3์ pq์ pushํ๋ค.
pq์์ popํ๋ฉด (2, 3)์ด ๋์ค๊ณ , 3์ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ด๋ฏ๋ก ์ ํํ๊ณ ๋ฐฉ๋ฌธ์ฒ๋ฆฌํ๋ค.
3๊ณผ ์ฐ๊ฒฐ๋ 1, 2, 4 ์ค์์ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ธ 4๋ฅผ pq์ pushํ๋ค.
pq์์ popํ๋ฉด (2, 4)๊ฐ ๋์ค๊ณ , 4๋ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ด๋ฏ๋ก ์ ํํ๊ณ ๋ฐฉ๋ฌธ์ฒ๋ฆฌํ๋ค.
4์ ์ฐ๊ฒฐ๋ 3, 5 ์ค์์ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ธ 5๋ฅผ pq์ pushํ๋ค.
pq์์ popํ๋ฉด (4, 1)์ด ๋์ค์ง๋ง 1์ ๋ฐฉ๋ฌธํ ์ ์ ์ด๋ฏ๋ก ์ ํํ์ง ์๋๋ค.
๋ค์ popํ๋ฉด (4, 3)์ด ๋์ค์ง๋ง 3 ๋ํ ๋ฐฉ๋ฌธํ ์ ์ ์ด๋ฏ๋ก ์ ํํ์ง ์๋๋ค.
๋ค์ popํ๋ฉด (6, 5)๊ฐ ๋์ค๊ณ , 5๋ ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ด๋ฏ๋ก ์ ํํ๊ณ ๋ฐฉ๋ฌธ์ฒ๋ฆฌํ๋ค.
5์ ์ฐ๊ฒฐ๋ 4๋ ๋ฐฉ๋ฌธํ ์ ์ ์ด๋ฏ๋ก ์๋ฌด๊ฒ๋ pushํ์ง ์๋๋ค.
pq๊ฐ ๋น์์ผ๋ฏ๋ก ๋ฐ๋ณต๋ฌธ์ ์ข
๋ฃํ๋ค.
import heapq
from collections import defaultdict
### Prim
def prim(graph):
v = len(graph)
visited = [0 for _ in range(v+1)]
pq = []
# initial setting
heapq.heappush(pq, (0, 1))
result = 0
# repitition
while pq:
weight, x = heapq.heappop(pq)
if visited[x]:
continue
visited[x] = 1
result += weight
for nx, weight in graph[x]:
if not visited[nx]:
heapq.heappush(pq, (weight, nx))
return result
Kruskal (non-recursion) | Kruskal (recursion) | Prim | |
---|---|---|---|
๊ธฐ์ค | ๊ฐ์ | ๊ฐ์ | ๋ ธ๋ |
์ฌ์ดํด ๋ฐฉ์ง ๋ฐฉ์ | Union-Find (non-recursion) | Union-Find (recursion) | visited ๋ฐฐ์ด |
์ฌ์ฉ ์๋ฃ๊ตฌ์กฐ | ์ ๋ ฌ + Union-Find | ์ ๋ ฌ + Union-Find | Priority Queue |
์ฌ์ฉ ์ํฉ | ์ ์ ์ ๋นํด ๊ฐ์ ์ด ๋ง์ ๊ฒฝ์ฐ | ์ ์ ์ ๋นํด ๊ฐ์ ์ด ๋ง์ ๊ฒฝ์ฐ | ๊ฐ์ ์ ๋นํด ์ ์ ์ด ๋ง์ ๊ฒฝ์ฐ |
์๊ฐ๋ณต์ก๋ | O(E log E) | O(E log E) | O(E log V) |
์ฃผ์์ฌํญ | โ | ์ฌ๊ท ๊น์ด ์ ํ์ ์ฃผ์ | โ |
๊ฐ๋จํ๊ฒ ํ
์ด๋ธ์ ํตํด ์ฐจ์ด์ ์ ์ ๋ฆฌํด๋ดค๋ค.
๋๊ฐ์ผ๋ฉด ์ฌ๋งํ๋ฉด Kruskal ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ ๊ฒ ๊ฐ๊ธด ํ๋ค.