๐[Tree] MST(์ต์์ ์ฅํธ๋ฆฌ)์ ๋ํด์โฆ
MST(์ต์ ์ ์ฅ ํธ๋ฆฌ)์ ๋ํด์โฆ
MST
๋ โ์ต์์ ์ฅํธ๋ฆฌโ๋ก, ๊ฐ์ฅ ๋น์ฉ์ด ์ ์ ๊ฒฝ๋ก๋ก ์ด๋ฃจ์ด์ง ํธ๋ฆฌ๋ฅผ ๋งํ๋ค.
MST๋ฅผ ์๊ธฐ ์ ์ Spanning Tree
์ฆ, ์ ์ฅํธ๋ฆฌ
๋ถํฐ ๋จผ์ ์์์ผ ํ๋ค.
1. Spanning Tree (์ ์ฅํธ๋ฆฌ)
Spanning Tree
๋ ๊ทธ๋ํ ๋ด์ ๋ชจ๋ vertex
๋ฅผ ํฌํจํ๋ ํธ๋ฆฌ์ด๋ค.
- Spanning Tree๋ ๊ทธ๋ํ์ โ์ต์ ์ฐ๊ฒฐ ๋ถ๋ถ ๊ทธ๋ํโ์ด๋ค. (์ฆ, ๊ทธ๋ํ์์ ์ผ๋ถ edge๋ฅผ ์ ํํด์ ๋ง๋ ํธ๋ฆฌ์ด๋ค)
- ์ต์ ์ฐ๊ฒฐ =
edge
์ ์๊ฐ ๊ฐ์ฅ ์ ์. - n๊ฐ์
vertex
๋ฅผ ๊ฐ๋ ๊ทธ๋ํ์ ์ต์edge
์ ์๋n-1
๊ฐ์ด๋ค. - n-1๊ฐ์ edge๋ก ์ฐ๊ฒฐ๋์ด ์์ผ๋ฉด ๋ฐ๋์ ํธ๋ฆฌํํ๊ฐ ๋๊ณ , ์ด ๊ฒ์
์ ์ฅํธ๋ฆฌ
๋ผ๊ณ ํ๋ค.
- ์ต์ ์ฐ๊ฒฐ =
1-1. Spanning Tree์ ํน์ง
DFS(๊น์ด์ฐ์ ํ์)
,BFS(๋๋น์ฐ์ ํ์)
์ ์ด์ฉํ์ฌ ๊ทธ๋ํ์์ ์ ์ฅํธ๋ฆฌ๋ฅผ ์ฐพ์ ์ ์๋ค.- ํ๋์ ๊ทธ๋ํ์๋ ๋ค์ํ ์ ์ฅํธ๋ฆฌ๊ฐ ์กด์ฌํ ์ ์๊ณ , ๊ทธ ์ค ๊ฐ์ฅ ์ ์ ๋น์ฉ์ ์ ์ฅํธ๋ฆฌ๋ฅผ
MST(์ต์์ ์ฅํธ๋ฆฌ)
๋ผ๊ณ ํ๋ค. - ์ ์ฅํธ๋ฆฌ๋ ํน์ํ ํํ์ ํธ๋ฆฌ์ด๋ฏ๋ก, ๋ชจ๋
vertex
๋ค์ดconnected
๋์ด ์์ด์ผ ํ๋ฉฐ,cycle
์ ํ์ฑํด์๋ ์๋๋ค. - n๊ฐ์ vertex๋ฅผ ์ ํํ n-1๊ฐ์ ๊ฐ์ ์ผ๋ก ์ฐ๊ฒฐํ๋ค.
2. MST (์ต์์ ์ฅํธ๋ฆฌ)
Spanning Tree
์ค์์ ์ฌ์ฉ๋ edge
์ weight(๊ฐ์ค์น)
์ ํฉ์ด ๊ฐ์ฅ ์์ ํธ๋ฆฌ์ด๋ค.
- ๊ทธ๋ํ์ ์๋ ๋ชจ๋ vertex๋ค์ ๊ฐ์ฅ ์ ์ ๋น์ฉ์ edge๋ค๋ก ์ฐ๊ฒฐํจ
[์์]
2-1. MST์ ํน์ง
- edge์ ๊ฐ์ค์น์ ํฉ์ด ์ต์์ฌ์ผ ํ๋ค.
- n๊ฐ์ vertex๋ฅผ ๊ฐ์ง๋ ๊ทธ๋ํ์ ๋ํด ๋ฐ๋์ n-1๊ฐ์ ๊ฐ์ ๋ง ์ฌ์ฉํ๋ค.
cycle
์ด ์์ด์ ์๋๋ค.- ๊ทธ๋ํ G์ MST T๋ฅผ ์ฐพ์๋ค๊ณ ํด์, ๊ทธ ํธ๋ฆฌ๊ฐ ์ ์ผํ MST๊ฐ ์๋ ์ ์๋ค. ์ฆ, ๋ค๋ฅธ MST Tโ์ด ์กด์ฌํ ์ ์๋ค.
2-2. MST์ ํ์ฅ
T : G์ MST, A๋ T์ subtree๋ผ๊ณ ํ์.
A์ V-A๋ฅผ ์ฐ๊ฒฐํ๋ edge(u,v)๋ฅผ `light edge`๋ผ๊ณ ํ์ ๋, edge(u,v)๋ MST-T์ ์ข
์๋๋ค.
[๊ณผ์ ]
edge(u,v)๊ฐ ๋น์ฉ์ด ๊ฐ์ฅ ์ ์ edge์ด๋ฉด, V-A์์ ๋
ธ๋(v)๋ฅผ A๋ก ๊ฐ์ ธ์จ๋ค. ์ด ๊ณผ์ ์ ๋ฐ๋ณตํ๋ฉด MST๋ฅผ ๊ตฌํ ์ ์๋ค.
safe edge
๋ โ๋น์ฉ(cost)๊ฐ ๊ฐ์ฅ ์ ๋ ดํ๋ฉด์ cycle์ ํ์ฑํ์ง ์๋ edgeโ๋ฅผ ๋งํ๋ค.
- S : vertex ์ ์ฒด์ ์งํฉ
- V : ์ ์ฒด ๊ทธ๋ํ ์งํฉ
- A : ์ ์ฒด edge ์งํฉ
- Cut : ๊ทธ๋ํ๋ฅผ Partition์ผ๋ก ๋๋๋๋ฐ ์ฌ์ฉ๋๋ค.
- ์) S์ V-S์ ํํฐ์ ์ผ๋ก ๋ถ๋ฆฌ
- Cross : edge(u,v)์์ u์ v๋ ๊ฐ๊ฐ ๋ค๋ฅธ ํํฐ์
์ ์กด์ฌํ๊ณ , ์ด๋ฅผ ์ฐ๊ฒฐํ๋ edge๋ฅผ
cross
๋ผ๊ณ ํ๋ค. - Respect : ์ด๋ค edge-set์์ cut์ ๊ฑด๋๊ฐ์ง ์๋ ๊ฒฝ์ฐ
- Light edge : cross-edge ์ค ๊ฐ์ฅ ์์ edge์ด๋ค.
2-3. MST ๊ตฌํ ์๊ณ ๋ฆฌ์ฆ
2-3-1. Generic-MST ์์ฌ์ฝ๋
2-3-2. Kruskal Algorithm (ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ)
Kruskal Algorithm
์ด๋ greedy algorithm(ํ์ ์๊ณ ๋ฆฌ์ฆ)
์ ์ด์ฉํ์ฌ ๊ทธ๋ํ์ ๋ชจ๋ vertex๋ฅผ ์ต์ ๋น์ฉ์ผ๋ก ์ฐ๊ฒฐํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
์ฆ, ๋น์ฉ์ด ๊ฐ์ฅ ์ผ edge๋ฅผ ์ ํํด ํธ๋ฆฌ๋ฅผ ๋ง๋ค์ด ๋๊ฐ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
- greedy algorithm : ๋ฏธ๋๋ฅผ ์๊ฐํ์ง ์๊ณ ๊ฐ ๋จ๊ณ์์ ๊ฐ์ฅ ์ต์ ์ ์ ํ์ ํ๋ ์๊ณ ๋ฆฌ์ฆ (์์ ์ ์ ํ์ด ์ต์ ์ ์ ํ์ด๊ธธ ๋ฐ๋ผ๋ ์๊ณ ๋ฆฌ์ฆ)
[๊ณผ์ ]
- ๊ทธ๋ํ์ edge๋ค์ weight์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ๋ค.
- ์ ๋ ฌ๋ edge๋ฆฌ์คํธ์์ ์์๋๋ก cycle์ ํ์ฑํ์ง ์๋ edge๋ฅผ ์ ํํ๋ค.
- ๊ฐ์ฅ ๋ฎ์ ๊ฐ์ค์น๋ฅผ ๋จผ์ ์ ํ
- cycle์ ๋ง๋๋ edge๋ ์ ์ธ
- ํด๋น edge๋ฅผ ํ์ฌ์ MST์ ์งํฉ์ ์ถ๊ฐํ๋ค.
[์์ฌ์ฝ๋]
[์์ ์ฝ๋] ์ฝ๋๋ ๋ค์ ๋ด๊ฐ ์ง๋ณผ๊ฒ๋๋ค..
- ํ์ด์ฌ(์ถ์ฒ)
from collections import deque
def mst():
def upward(buf, idx):
parent = mst_nodes[idx]
if parent < 0:
return idx
buf.append(idx)
return upward(buf, parent)
def find(idx):
buf = []
result = upward(buf, idx)
for i in buf:
mst_nodes[i] = result
return result
def union(x, y):
x, y = find(x), find(y)
if x == y:
return False
if mst_nodes[x] < mst_nodes[y]:
mst_nodes[y] = x
elif mst_nodes[x] > mst_nodes[y]:
mst_nodes[x] = y
else:
mst_nodes[x] -= 1
mst_nodes[y] = x
return True
V, E = 6, 9
edges = [[1, 2, 6], [1, 3, 3], [2, 3, 2], [2, 4, 5],
[3, 4, 3], [3, 5, 4], [4, 5, 2], [4, 6, 3], [5, 6, 5]]
edges.sort(key=lambda x: x[2])
mst_graph = [[0] * V for _ in range(V)]
mst_nodes = [-1 for _ in range(V)]
mst = []
cost = 0
q = deque(edges)
while True:
u, v, w = q.popleft()
udx, vdx = u - 1, v - 1
if union(udx, vdx) is False:
continue
mst.append((u, v))
mst_graph[udx][vdx] = 1
mst_graph[vdx][udx] = 1
cost += w
if len(mst) == V - 1:
break
print(f'mst cost is {cost}')
print(mst)
for row in mst_graph:
print(*row)
mst()
- ์๋ฐ(์ถ์ฒ)
import java.util.Arrays;
import java.util.Scanner;
/*
sample input(์ฒซ ์ค์ ์ฒซ ์ซ์๋ ์ ์ ์ ๊ฐ์, ๋ ๋ฒ์งธ ์ซ์๋ ๊ฐ์ ์ ๊ฐ์).
6 9
1 6 5
2 4 6
1 2 7
3 5 15
5 6 9
3 4 10
1 3 11
2 3 3
4 5 7
*/
public class Kruskal {
static int V, E;
static int[][] graph;
// ๊ฐ ๋
ธ๋์ ๋ถ๋ชจ
static int[] parent;
// ์ต์ข
์ ์ผ๋ก ์ฐ๊ฒฐ๋ ์ต์ ์ ์ฅ ํธ๋ฆฌ ์ฐ๊ฒฐ ๋น์ฉ.
static int final_cost;
public static void main(String[] args) {
// ๊ทธ๋ํ์ ์ฐ๊ฒฐ์ํ(๋
ธ๋1, ๋
ธ๋2, ๋น์ฉ)๋ฅผ ์ด๊ธฐํ.
Scanner sc = new Scanner(System.in);
V = sc.nextInt();
E = sc.nextInt();
graph = new int[E][3];
for (int i = 0; i < E; i++) {
graph[i][0] = sc.nextInt();
graph[i][1] = sc.nextInt();
graph[i][2] = sc.nextInt();
}
parent = new int[V];
final_cost = 0;
// ๊ฐ์ ๋น์ฉ ์์ผ๋ก ์ค๋ฆ์ฐจ์ ์ ๋ ฌ
Arrays.sort(graph, (o1, o2) -> Integer.compare(o1[2], o2[2]));
// makeSet
for (int i = 0; i < V; i++) {
parent[i] = i;
}
// ๋ฎ์ ๋น์ฉ๋ถํฐ ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ ์งํ
for (int i = 0; i < E; i++) {
// ์ฌ์ดํด์ด ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ์๋ง ๊ฐ์ ์ ์ ํํ๋ค(์ฌ๊ธฐ์๋ ์ต์ข
๋น์ฉ๋ง ๊ณ ๋ คํ๋๋ก ํ๊ฒ ๋ค).
if (find(graph[i][0] - 1) != find(graph[i][1] - 1)) {
System.out.println("<์ ํ๋ ๊ฐ์ >");
System.out.println(Arrays.toString(graph[i]));
union(graph[i][0] - 1, graph[i][1] - 1);
final_cost += graph[i][2];
System.out.println("<๊ฐ ๋
ธ๋๊ฐ ๊ฐ๋ฆฌํค๊ณ ์๋ ๋ถ๋ชจ>");
System.out.println(Arrays.toString(parent) + "\n");
continue;
}
}
System.out.println("์ต์ข
๋น์ฉ : " + final_cost);
sc.close();
}
private static void union(int a, int b) {
a = find(a);
b = find(b);
if (a > b) {
parent[a] = b;
} else {
parent[b] = a;
}
}
private static int find(int x) {
if (parent[x] == x)
return x;
else
return find(parent[x]);
}
}
2-3-3. Prim Algorithm (ํ๋ฆผ ์๊ณ ๋ฆฌ์ฆ)
Prim Algorithm
์ด๋ ์์ ๋
ธ๋์์ ๋
ธ๋๋ฅผ ์ถ๊ฐํด๊ฐ๋ฉฐ ๋จ๊ณ์ ์ผ๋ก ํธ๋ฆฌ๋ฅผ ํ์ฅํด๋๊ฐ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
[์์ฌ์ฝ๋]
[์์ ์ฝ๋]
from collections import defaultdict
import heapq
def mst():
V, E = 6, 9
edges = [[1, 2, 6], [1, 3, 3], [2, 3, 2], [2, 4, 5],
[3, 4, 3], [3, 5, 4], [4, 5, 2], [4, 6, 3], [5, 6, 5]]
graph = defaultdict(list)
for srt, dst, weight in edges:
graph[srt].append((dst, weight))
graph[dst].append((srt, weight))
mst_graph = [[0] * V for _ in range(V)]
mst_nodes = [-1 for _ in range(V)]
visited = [True for _ in range(V)]
q = [(0, 1, 1)]
while q:
cost, node, prev = heapq.heappop(q)
if visited[node - 1] is False:
continue
visited[node - 1] = False
mst_graph[node - 1][prev - 1] = 1
mst_graph[prev - 1][node - 1] = 1
mst_nodes[node - 1] = cost
for dst, weight in graph[node]:
if visited[dst - 1] is True:
heapq.heappush(q, (weight, dst, node))
print(f'MST cost is {sum(mst_nodes)}')
mst_graph[0][0] = 1
for row in mst_graph:
print(*row)
mst()
2-3-4. ๋ ์๊ณ ๋ฆฌ์ฆ์ ์๊ฐ๋ณต์ก๋ ๋น๊ต
Kruskal Algorithm
์ ์๊ฐ๋ณต์ก๋ : O(eloge)
Prim Algorithm
์ ์๊ฐ๋ณต์ก๋ : O(n^2)
[๋น๊ต]
๊ทธ๋ํ์ edge๊ฐ ์ ์ ๊ทธ๋ํ์ธ ํฌ์๊ทธ๋ํ(Sparse Graph)
์ธ ๊ฒฝ์ฐ์๋ Kruskal Aogorithm
์ด ์ ๋ฆฌํ๋ค.
๊ทธ๋ํ์ edge๊ฐ ๋ง์ ๊ทธ๋ํ์ธ ๋ฐ์ง ๊ทธ๋ํ(Dense Graph)
์ธ ๊ฒฝ์ฐ์๋ Prim Algorithm
์ด ์ ๋ฆฌํ๋ค.
๋๊ธ๋จ๊ธฐ๊ธฐ