์ต์ ์ ์ฅ ํธ๋ฆฌ(Minimum Spanning Tree, MST)์ด๋?
์ต์ ์ ์ฅ ํธ๋ฆฌ๋ฅผ ๋ฐฐ์ฐ๊ธฐ ์์, ์ ์ฅ ํธ๋ฆฌ๋ ๋ฌด์์ธ์ง ์์์ผ ํ๋ค. ์ด๋ ์ฐ๊ฒฐ ๊ทธ๋ํ์ ๋ถ๋ถ ๊ทธ๋ํ๋ก, ๋ชจ๋ ์ ์ ๊ณผ ๊ฐ์ ์ ๋ถ๋ถ์งํฉ์ผ๋ก ๊ตฌ์ฑ๋๋ค. ์ ์ฅ ํธ๋ฆฌ์ ์ค์ํ ํน์ง ์ค ํ๋๋ ๋ชจ๋ ๋ ธ๋๊ฐ ์ ์ด๋ ํ๋์ ๊ฐ์ ๊ณผ ์ ์ ์ ์ฐ๊ฒฐ๋์ด์ผ ํ๋ฉฐ, ์ฌ์ดํด์ ๋ง๋ค๋ฉด ์๋๋ค. ์ต์ ์ ์ฅ ํธ๋ฆฌ๋ฅผ ์ดํดํ๊ธฐ ์ํด์๋ ์ด๋ฌํ ์ ์ ํธ๋ฆฌ์ ๊ฐ๋ ์ ์ ํํ ํ์ ํ๊ณ ์์ด์ผ ํ๋ค.
์๋์ ๊ฐ์ ๊ทธ๋ํ๊ฐ ์ ์ฅ ํธ๋ฆฌ์ ์์ ์ค ํ๋์ด๋ค.
์ต์ ์ ์ฅ ํธ๋ฆฌ๋ ํ๋์ ์ฐ๊ฒฐ ์ฑ๋ถ์ผ๋ก ์ด๋ฃจ์ด์ง ๋ฌด๋ฐฉํฅ ๊ฐ์ค์น ๊ทธ๋ํ์์ ๊ฐ์ ์ ๊ฐ์ค์น์ ํฉ์ด ์ต์์ธ ์ ์ฅํธ๋ฆฌ๋ฅผ ๋งํ๋ค.
์ด๋ฌํ ์ต์ ์ ์ฅ ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ๋ํ์ ์ผ๋ก Kruskal, Prim, Sollin ์๊ณ ๋ฆฌ์ฆ์ด ์๋ค. ์ด๋ ๋ชจ๋ ๊ทธ๋ฆฌ๋(Greedy)์๊ณ ๋ฆฌ์ฆ์ด๋ค. ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ต์ ํด(์ต์๊ฐ, ์ต๋๊ฐ) ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์๊ณ ๋ฆฌ์ฆ ๋ฐฉ์์ผ๋ก ์๊ณ ๋ฆฌ์ฆ์ ์ ํ์ด ํญ์ "์์ฌ๋ด์ด" ์ต์ ํน์ ์ต๋๊ฐ์ธ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
๋ค์๋งํด, ์ต์ ์ ์ฅ ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ํ์ฌ์ ์ ํ์ด ์ต์ ์ ์ ํ์ด๋ผ๊ณ ์๊ฐํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ผ๋ ๊ฒ์ด๋ค. ์ด์ ๋ถํฐ, ์ด ์ต์ ์ ์ฅ ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ด ๊ตฌ์ฒด์ ์ผ๋ก ์ด๋ป๊ฒ ๋์ํ๋ ์ง ์ดํด๋ณด๋๋ก ํ๊ฒ ๋ค.
Kruskal ์๊ณ ๋ฆฌ์ฆ
Krusal ์๊ณ ๋ฆฌ์ฆ์ ํต์ฌ์ ๊ฐ์ ์ ๊ฐ์ค์น๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ๋ค๋ ๊ฒ์ด๋ค. ์ฌ์ค์ ์ด๊ฒ ์ ๋ถ์ธ ๊ฐ๋จํ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ๋ฌผ๋ก , ์ ์ฅ ํธ๋ฆฌ์ ์ ์ ์ ์ฌ์ดํด์ ๋ง๋ค๋ฉด ์๋๊ธฐ ๋๋ฌธ์ ์ด๋ ์ ์ธํ๋ฉฐ ์ด๋ฅผ ์ํด Union - Find ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ค.
์ฆ, ๊ฐ์ ๋ค์ ์ ํํ๋๋ฐ "์ฌ์ดํด์ ๋ง๋ค์ง ์๊ณ , ํญ์ ์์ฌ๋ด์ด ๊ฐ์ค์น๊ฐ ์์ ๊ฐ์ " ์ ์ ํํ๊ณ , ์ฌ์ดํด์ ํ์ฑ ์ ๋ฌด ํ๋จ์ ์ํด Union - Find๋ฅผ ์ฌ์ฉํ๋ค๊ณ ์ ๋ฆฌํ ์ ์๋ค.
๊ทธ๋ฌ๋ฉด ์ด๋ป๊ฒ ํ๋ฉด Union - Find๋ฅผ ์ฌ์ฉํด ์ฌ์ดํด์ด ๋ง๋ค์ด์ง๋ ์ง ํ์ธํ ๊น? ์ด๋ ์ ๋ ์ ์ ์ด ๊ฐ์ ์งํฉ์ ์ํ๋ ์ง์ ๋ฐ๋ผ ํ๋จ๋๋ค. ๋ง์ฝ ๋ค๋ฅธ ์งํฉ์ ์ํด์ ธ ์๋ค๋ฉด ์ฌ์ดํด์ ๋๊ณ ์๋ ๊ฒ์ด ์๋์ง๋ง, ๊ฐ์ ์งํฉ์ด๋ผ๋ฉด ์ฌ์ดํด์ ๋๊ณ ์๋ ๊ฒ์ด๋ค.
Kruskal ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํ
๊ฐ๋ ์์ฒด๊ฐ ๊ทธ๋ฆฌ ์ด๋ ต์ง ์๊ธฐ ๋๋ฌธ์ ๊ตฌํ๋ ์ฝ๋ค. ์๋๋ ์๋ฐ๋ก ๊ตฌํํ Kruskal ์๊ณ ๋ฆฌ์ฆ์ ์์์ด๋ค.
class KruskalMST {
int N, M;
List<Edge>[] graph;
UnionFind uf;
Edge[] tree;
// ๊ฐ์ค์น๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ๊ธฐ ์ํ ์ฝ๋(Comparator ์ฌ์ฉ)
static class Weight_Comparison implements Comparator<Edge> {
public int compare(Edge e, Edge f) {
if (e.weight > f.weight)
return 1;
else if (e.weight < f.weight)
return -1;
return 0;
}
}
// ์์ฑ์ ์ด๊ธฐํ
public KruskalMST(List<Edge>[] adjList, int numOfEdges) {
N = adjList.length;
M = numOfEdges;
graph = adjList;
uf = new UnionFind(N);
tree = new Edge[N-1];
}
// ์ค์ง์ ์ผ๋ก ์ต์ ์ ์ฅ ํธ๋ฆฌ๋ฅผ ๊ตฌํ๋ ๋ถ๋ถ
public Edge[] mst() {
// ์ฐ์ ์์ ํ์ ๊ฐ์ค์น ์ ๋ ฌ์ ์ํ ์กฐ๊ฑด์ ์ถ๊ฐ
Weight_Comparison BY_WEIGHT = new Weight_Comparison();
PriorityQueue<Edge> pq = new PriorityQueue<Edge>(M, BY_WEIGHT);
for(int i=0; i<N; i++) {
for(Edge e : graph[i]) {
pq.add(e);
}
}
// u์ v ์ฆ, ๊ฐ์ ์ ์ ๋์ ์ด ๊ฐ์ ์งํฉ์ ์ํ๋ ์ง ํ์ธ
int count = 0;
while(!pq.isEmpty() && count < N-1) {
Edge e = pq.poll();
int u = e.vertex;
int v = e.adjvertex;
// ์ ๋ ์ ์ด ๋ค๋ฅด๋ค๋ฉด, union์ ํตํด ๋ถ๋ชจ ํต์ผ, tree์ ์ถ๊ฐ
if (!uf.isConnected(u, v)) {
uf.union(u, v);
tree[count++] = e;
}
}
return tree;
}
}
class UnionFind {
protected int[] p;
protected int[] rank;
// ์ด๊ธฐํ, ์ฒ์์๋ ์๊ธฐ ์์ ์ด ๋ถ๋ชจ๊ฐ ๋๋ค.
public UnionFind(int N) {
p = new int[N];
rank = new int[N];
for(int i=0 ;i<N; i++) {
p[i] = i;
rank[i] = 0;
}
}
// find๋ฅผ ํตํด์ ๋ถ๋ชจ๋ฅผ ๋ฐํ
protected int find(int i) {
if (i!=p[i]) {
p[i] = find(p[i]);
}
return p[i];
}
// ๋ถ๋ชจ๊ฐ ๊ฐ์ ์ง ํ์ธํ๋ ํจ์
public boolean isConnected(int i, int j) {
return find(i) == find(j);
}
// i์ j์ ๋ถ๋ชจ๋ฅผ ํ์ธํ๊ณ ๊ฐ๋๋ก ์
๋ฐ์ดํธ
public void union(int i, int j) {
int iroot = find(i);
int jroot = find(j);
if (iroot == jroot) return;
if (rank[iroot] > rank[jroot]) {
p[jroot] = iroot;
} else if(rank[iroot] < rank[jroot]) {
p[iroot] = jroot;
} else {
p[jroot] = iroot;
rank[iroot]++;
}
}
}
class Edge {
int vertex, adjvertex;
int weight;
public Edge(int u, int v, int wt) {
vertex = u;
adjvertex = v;
weight = wt;
}
}
์กฐ๊ธ ์ฃผ์ํด์ ๋ณด์์ผ ํ ๊ฒ์ Union-Find ํด๋์ค์ด๋ค. ์ด ํด๋์ค์์ union ํจ์๋ ์ ๋ ๊ทธ๋ฃน์ ๋ํ ๋ถ๋ชจ๊ฐ ๋ค๋ฅผ ๋, ํ ๊ทธ๋ฃน์ ๋ค๋ฅธ ๊ทธ๋ฃน์ ํฉ์น๋ ํจ์์ด๋ค. ์ด๋ rank๋ผ๋ ํธ๋ฆฌ์ ๋์ด๋ฅผ ๋ํ๋ด๋ ๋ฐฐ์ด์ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ธํด ๋ณผ ํ์๊ฐ ์๋ค.
rank ํธ๋ฆฌ์ ๋์ด๋ฅผ ๋ํ๋ธ๋ค๊ณ ํ๋๋ฐ, ์ด๋ฅผ ์ ์ ํ ์กฐ์ ํ๋ฉฐ unionํ๋ค๋ฉด ํธ๋ฆฌ์ ๋ถ๊ท ํ์ ์ค์ผ ์ ์๋ค. ์ด๋ฅผ ๋ญํฌ ์ต์ ํ๋ผ๊ณ ํ๋ค. ๋ญํฌ ์ต์ ํ๋ฅผ ํตํด์ ์ ์ฒด ์ฐ์ฐ์ ํจ์จ์ฑ์ ํฅ์ ์ํฌ ์ ์๋ ์ด์ ์ด ์๋ค.
์๋ฌดํผ, union ์ ์ด๋ฌํ rank๋ฅผ ํ์ธํ๋ ๊ณผ์ ์ด ์กด์ฌํ๋ค. rank๊ฐ ๋ฎ์ ํธ๋ฆฌ๋ฅผ ๋์ ํธ๋ฆฌ์ ๋ง์ถ๋ค. ๊ทธ๋ ๊ฒ ํด์ผ ํธ๋ฆฌ์ ์ข์ฐ ๋ถ๊ท ํ์ด ํด์๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๋ ๊ทธ๋ฆผ์ ๋ณด๋ฉด ์กฐ๊ธ ๋ ์ดํด๊ฐ ์ฌ์ธ ๊ฒ์ด๋ค.
๋ ๋ญํฌ๊ฐ ๊ฐ์ ๊ฒฝ์ฐ๋ผ๋ฉด, ๋ ์ค ์์์ ๋ถ๋ชจ๋ฅผ ์ ํํ๊ณ rank๋ฅผ ์ฌ๋ ค์ค ์ ๋ฐ์ ์๊ธฐ๋ ํ๋ค. Union - Find์ ๊ณผ์ ์ ์๊ฐ๋ณด๋ค ๋ง์ด ์ค์ํ๋ฏ๋ก, ๊ผญ ์์งํด ๋๋๋ก ํ์.
ํ๋ก๊ทธ๋จ ์คํ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
Prim ์๊ณ ๋ฆฌ์ฆ
Prim ์๊ณ ๋ฆฌ์ฆ๋ ๊ฐ๋จํ๋ค. Prim ์๊ณ ๋ฆฌ์ฆ์ ์์์ ์์์ ์์ ๊ฐ์ฅ ๊ฐ๊น์ด ์ ์ ์ ์ถ๊ฐํ์ฌ ๊ฐ์ ์ด ํ๋์ ํธ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ , ๋ง๋ค์ด์ง ํธ๋ฆฌ์ ๊ฐ์ฅ ๊ฐ๊น์ด ์ ์ ์ ํ๋์ฉ ์ถ๊ฐํ์ฌ MST๋ฅผ ๋ง๋ค ์ ์๋ค.
๋ค์๋งํด ํ๋์ ์ ์ ์์ ์์ํ๋๋ฐ, ๊ทธ ์ ์ ๊ณผ ์ฐ๊ฒฐ๋์ด ์๋ ์ ์ ์ค, ๊ฐ์ฅ ๊ฐ์ค์น๊ฐ ์์ ๊ฐ์ ์ ํํ๋ค. ์ดํ, ์ ํํ ๊ฐ์์ ๋ค์ ์ฐ๊ฒฐ๋์ด ์๋ ์ ์ ์ ์ฐพ๊ณ , ๊ฐ์ค์น ์์ ๊ฐ์ ์ฐพ๋ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
์ด๋, ํธ๋ฆฌ์ ์ํ์ง ์๋ ๊ฐ ์ ์ ๊ณผ ์์ ๊ฐ์ค์น์ ๊ฐ์ ์ฐพ๊ธฐ ์ํด ํ๋์ ๋ฐฐ์ด์ ์ด์ฉํ๋ ๊ฒ์ด ํน์ง์ด๋ค. ์ฝ๋๋ฅผ ํตํด ๊ตฌํ ๊ณผ์ ์ ์ดํด๋ณด๋๋ก ํ์.
Prim ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํ
class Edge {
int adjvertex;
int weight;
public Edge(int v, int wt) {
adjvertex = v;
weight = wt;
}
}
class PrimMST {
int N;
List<Edge>[] graph;
public PrimMST(List<Edge>[] adjList) {
N = adjList.length;
graph = adjList;
}
public int[] mst (int s) {
// ๋ฐฉ๋ฌธ ์ฒดํฌ ๋ฐฐ์ด
boolean[] visited = new boolean[N];
int[] D = new int[N];
int[] previous = new int[N];
// ์ด๊ธฐํ, ๋ฐฉ๋ฌธ์ ๋ชจ๋ false, ์ด์ ๋ฐฉ๋ฌธ ๋
ธ๋๋ฅผ -1๋ก ์ด๊ธฐํ, D ๋ฐฐ์ด์ ์ฌ์ค ์ ๊ฐ์ค์น๋ฅผ ๋ชจ์๋๋ ๋ฐฐ์ด
for(int i=0; i<N; i++) {
visited[i] = false;
previous[i] = -1;
D[i] = Integer.MAX_VALUE;
}
previous[s] = 0;
D[s] = 0;
for(int k=0; k<N; k++) {
int minVertex = -1;
int min = Integer.MAX_VALUE;
// ๋ฐฉ๋ฌธํ์ง ์์์ผ๋ฉฐ, D ๋ฐฐ์ด์์ ๊ฐ์ฅ ์์ ๊ฐ ์ฐพ๊ธฐ(๊ฐ์ฅ ์์ ๊ฐ์ค์น ๊ฐ)
for(int j=0; j<N; j++) {
if ((!visited[j]) && (D[j] < min)) {
min = D[j];
minVertex = j;
}
}
// ๊ฐ์ฅ ์์ ๊ฐ์ค์น ๊ฐ์ ๊ฐ์ง ์ด์ ์ ์ ๋ฐฉ๋ฌธ(minVertex ๋ฐฉ๋ฌธ)
visited[minVertex] = true;
// minVertex์ ์ด์๋
ธ๋ ํ์
for(Edge i : graph[minVertex]) {
// ๊ทธ ์ด์์ ๋ฐฉ๋ฌธํ์ง ์์๋ค๋ฉด,
if (!visited[i.adjvertex]) {
// ํธ๋ฆฌ์ ์ถ๊ฐ๋์ง ์์ ๊ฐ์ด๋ผ๋ฉด, MAX_VALUE์ ๊ฐ์ ๊ฐ์ง ๊ฒ์
int currentDist = D[i.adjvertex];
// ์ด์์ ๊ฐ์ค์น
int newDist = i.weight;
// ํธ๋ฆฌ์ ์ถ๊ฐ๋์ง ์์ ์ด์์ด๋ผ๋ ๋ป
if (newDist < currentDist) {
// D ๋ฐฐ์ด์ ์ด์์ ๊ฐ์ค์น ๊ฐ ์ถ๊ฐ
D[i.adjvertex] = newDist;
// ์ด์์ ์ด์ ๊ฐ์ minVertex ์ถ๊ฐ, ์ฆ ๋ฐฉ๋ฌธ์ด ํ์ ๋ ๊ฒ์
previous[i.adjvertex] = minVertex;
}
}
}
}
// ๋ฐฉ๋ฌธ์ด ํ์ ๋ previous ๋ฐฐ์ด์ ๋ฆฌํด = MST ๊ฐ ๋ฐํ
return previous;
}
}
๋์ฌ๊ฒจ ๋ณผ ๊ฒ์ (๊ฐ์ฅ ์์ ๊ฐ์ค์น์ ๊ฐ์ ์ฐฉ๊ณ ) + (MST ํธ๋ฆฌ์ ์ถ๊ฐ๋์ง ์์ minVertex์ ์ด์ ์ ์ ) ์ด๋ผ๋ ๋ ์กฐ๊ฑด์ ๋ง์กฑ์ํค๊ธฐ ์ํด ๊ฐ์ค์น ๊ฐ์ ๋ด์ D ๋ฐฐ์ด์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ด๋ค.
์ด๊ธฐ์ D ๋ฐฐ์ด์ Integer.MAX_VALUE ๊ฐ์ผ๋ก ์ง์ ํด๋๊ณ , MST ํธ๋ฆฌ์ ์ถ๊ฐ๋์ง ์์ minVertex์ ์ด์ D๊ฐ ๋ง์ ์ค์ ๊ฐ์ค์น ๊ฐ์ผ๋ก ๋๋ค. ์ด๋ก ์ธํด, (MST ํธ๋ฆฌ์ ์ถ๊ฐ๋์ง ์์ minVertex์ ์ด์ ์ ์ ) ์ด๋ผ๋ ์กฐ๊ฑด์ ์งํฌ ์ ์๋ ๊ฒ์ด๋ค.
์ด ์ดํ, for๋ฌธ์ ๋๋ฉด์ D ๋ฐฐ์ด ์ค ๊ฐ์ฅ ์์ ๊ฐ๋ง ์ฐพ๊ฒ๋๋ฉด ๊ฐ์ฅ ์์ ๊ฐ์ค์น๋ฅผ ์ป๊ฒ๋๋ ๊ฒ์ด๋ค.
ํ๋ก๊ทธ๋จ์ ์คํ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
Sollin ์๊ณ ๋ฆฌ์ฆ
๋ง์ง๋ง์ผ๋ก Sollin ์๊ณ ๋ฆฌ์ฆ์ด๋ค. Sollin ์๊ณ ๋ฆฌ์ฆ์ ํต์ฌ์ ๊ฐ ์ ์ ์ ๋ ๋ฆฝ๋ ํธ๋ฆฌ๋ก ๋ณด๋ ๊ฒ์ด๋ค.
์ฆ, ๊ฐ ํธ๋ฆฌ์ ์ด์ํ ์ ์ ์์ ๊ฐ์ค์น๊ฐ ๊ฐ์ฅ ์์ ๊ฐ์ ์ ์ ํํด ๋๊ฐ๋ค. ์ดํ ํธ๋ฆฌ๊ฐ ํฉํด์ง๋ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ๊ณ ์ด๋ 1๊ฐ์ ํธ๋ฆฌ๊ฐ ๋ง๋ค์ด์ง ๋๊น์ง ๋ฐ๋ณต๋๋ค. ์ฌ์ค ์ ์ดํดํ๊ธฐ๋ ์ ์ผ ์ฌ์ด ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ๋ฐ๋ก ๊ตฌํ์ ์ดํด๋ณด์.
Sollin ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํ
import java.util.ArrayList;
import java.util.List;
class Edge {
int src, dest, weight;
public Edge(int src, int dest, int weight) {
this.src = src;
this.dest = dest;
this.weight = weight;
}
}
public class SollinMST {
public static List<Edge> findMST(List<Edge> edges, int V) {
List<Edge> minSpanningTree = new ArrayList<>();
int[] cheapest = new int[V]; // cheapest[i]๋ i๋ฒ ์ ์ ์ ์ฐ๊ฒฐํ๋ ๊ฐ์ฅ ๊ฐ์ค์น๊ฐ ๋ฎ์ ๊ฐ์ ์ ๊ฐ์ค์น๋ฅผ ์ ์ฅ
int[] closest = new int[V]; // closest[i]๋ i๋ฒ ์ ์ ๊ณผ ์ฐ๊ฒฐ๋๋ ๊ฐ์ฅ ๊ฐ์ค์น๊ฐ ๋ฎ์ ๊ฐ์ ์ ๋ชฉ์ ์ ์ ์ ์ ์ฅ
int[] component = new int[V]; // ๊ฐ ์ ์ ์ด ์ํ ์ฐ๊ฒฐ ์์์ ๋ฒํธ
// ์ด๊ธฐํ
for (int i = 0; i < V; i++) {
cheapest[i] = Integer.MAX_VALUE; // ๋ชจ๋ cheapest ๋ฐฐ์ด ๊ฐ ์ด๊ธฐํ
closest[i] = -1; // ๋ชจ๋ closest ๋ฐฐ์ด ๊ฐ ์ด๊ธฐํ
component[i] = i; // ๋ชจ๋ ์ ์ ์ด ์ฒ์์๋ ์์ ์ ๋จ์ผ ์ฐ๊ฒฐ ์์๋ก ๊ฐ์ง
}
int numComponents = V; // ์ด๊ธฐ ์ฐ๊ฒฐ ์์ ์๋ ์ ์ ์์ ๊ฐ์
// ์ต์ ์ ์ฅ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ ๋๊น์ง ๋ฐ๋ณต
while (numComponents > 1) {
// ๋ชจ๋ ๊ฐ์ ์ ์ํํ๋ฉฐ cheapest์ closest ๋ฐฐ์ด์ ์
๋ฐ์ดํธ
for (Edge edge : edges) {
// ํ์ฌ ๊ฐ์ ์ ์ถ๋ฐ์ ๊ณผ ๋์ฐฉ์ ์ด ์ํ ์ฐ๊ฒฐ ์์๋ฅผ ๊ฐ์ ธ์จ๋ค.
int component1 = component[edge.src];
int component2 = component[edge.dest];
// ์๋ก ๋ค๋ฅธ ์ฐ๊ฒฐ ์์์ด๊ธฐ ๋๋ฌธ์ ํ๋ณด ๊ฐ์ ์ด ๋๋ค.
if (component1 != component2) {
// ์ต์ ๊ฐ์ค์น ์ ์
if (edge.weight < cheapest[component1]) {
cheapest[component1] = edge.weight;
closest[component1] = edge.dest;
}
if (edge.weight < cheapest[component2]) {
cheapest[component2] = edge.weight;
closest[component2] = edge.src;
}
}
}
// ๋ชจ๋ ์ ์ ์ ์ํํ๋ฉฐ ์ฐ๊ฒฐ ์์๋ฅผ ๋ณํฉํ๋ฉด์ ์ต์ ์ ์ฅ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑ
for (int i = 0; i < V; i++) {
if (closest[i] != -1) {
// ํ์ฌ ์ ์ ๊ณผ ์ฐ๊ฒฐ ์์๋ฅผ ๊ฐ์ ธ์ด
int component1 = component[i];
int component2 = component[closest[i]];
if (component1 != component2) {
// ๋ ์ฐ๊ฒฐ ์์๋ฅผ ๋ณํฉ
minSpanningTree.add(new Edge(i, closest[i], cheapest[i]));
numComponents--;
int oldComponent = component1;
int newComponent = component2;
// ์ฐ๊ฒฐ ์์๋ฅผ ์
๋ฐ์ดํธ
for (int j = 0; j < V; j++) {
if (component[j] == oldComponent) {
component[j] = newComponent;
}
}
}
closest[i] = -1;
}
}
}
return minSpanningTree;
}
public static void main(String[] args) {
int V = 4; // ์ ์ ์ ์
List<Edge> edges = new ArrayList<>();
edges.add(new Edge(0, 1, 2));
edges.add(new Edge(0, 2, 3));
edges.add(new Edge(1, 2, 2));
edges.add(new Edge(1, 3, 4));
edges.add(new Edge(2, 3, 1));
List<Edge> minSpanningTree = findMST(edges, V);
System.out.println("์ต์ ์ ์ฅ ํธ๋ฆฌ ๊ฐ์ :");
for (Edge edge : minSpanningTree) {
System.out.println(edge.src + " - " + edge.dest + " : " + edge.weight);
}
}
}
๋ ผ๋ฆฌ์ ์ผ๋ก๋ ์ดํดํ๊ธฐ ์ฌ์ฐ๋, ์๊ฐ ์ธ๋ก ์ฝ๋ ๊ตฌํ์ ์๊ฐ์ด ๊ฑฐ๋ฆฌ๋ ๋ฏ ์ถ๋ค. ์ต์ ์ ์ฅ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํด ๋ชจ๋ ์ ์ ์ ํ๋์ ํธ๋ฆฌ๋ก ๋ณด์ ๋ณ๋ ฌ์ ์ผ๋ก ํ์์ ํ๊ณ , ์ต์ ๊ฐ์ค์น๋ฅผ ๊ฐ๊ฐ ์ฐพ๋๋ค. ์ดํ, ๊ฐ์ฅ ์์ ๊ฐ์ค์น๋ฅผ ๊ฐ์ง ๊ฐ์ ๋ค์ ์ฐ๊ฒฐ์์ผ์ฃผ๊ณ ํธ๋ฆฌ๊ฐ ํฉ์ณ์ง๋ ๊ฒฝ์ฐ๋ ์ฒ๋ฆฌํ๋ค.
๊ฐ ์๊ณ ๋ฆฌ์ฆ์ ์๊ฐ ๋ณต์ก๋
- Kruskal
- ๊ฐ์ ์ ์ ๋ ฌํ๋๋ฐ, ์์๋๋ ์๊ฐ : O(mlogn)
- ์ ์ฅํธ๋ฆฌ๊ฐ ๋ง๋ค์ด ์ง ๋๊น์ง ๊ฐ์ ์ ๋ํด isConnected()์ union() ์ํํ๋ ์๊ฐ : O((m+n) log * n)
- O(mlogn) + O((m+n) log * n) = O(mlogn)
- Prim
- minVertex๋ฅผ ์ฐพ๊ธฐ ์ํด ์ด์ง ํ(Binary Heap)์ ์ฌ์ฉํ๋ฉด, ๊ฐ ๊ฐ์ ์ ๋ํ D ์์๋ฅผ ๊ฐฑ์ ํ๋ฉฐ ํ ์ฐ์ฐ์ ์ํํด์ผํ๋ฏ๋ก, O(mlogn)
- ์ด์ง ํ์ ๊ฐ ์ ์ ์ ๋์๋๋ D ์์๋ฅผ ์ ์ฅํ๋ฏ๋ก, ํ์ ์ต๋ ํฌ๊ธฐ๋ n
- ๊ฐ์ค์น๊ฐ ๊ฐฑ์ ๋์ด ๊ฐ์๋์์ ๋์ ํ ์ฐ์ฐ์๋ O(logn)์๊ฐ
- ์ ๋ ฅ ๊ทธ๋ํ๊ฐ ํฌ์ ๊ทธ๋ํ๋ผ๋ฉด, m = O(n)์ด๋ฉด, ์ํ ์๊ฐ์ด O(mlogn) = O(nlogn)์ด๋ฏ๋ก ์ด์ง ํ์ ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์จ์ ์ด๋ค.
- ๋ง์ฝ ํผ๋ณด๋์น ํ์ ์ฌ์ฉํ๋ค๋ฉด O(nlogn + m) ์๊ฐ ์์, ๋ค๋ง ๊ตฌํ์ด ์ด๋ ค์ ์ด๋ก ์ ์ธ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
- Sollin
- repeat - ๋ฃจํ๊ฐ ๊ฐ ์์ ํธ๋ฆฌ๊ฐ ์๋ก ์ฐ๊ฒฐ๋ ๊ฐ์ ์ ์ ํํ๋ ๊ฒฝ์ฐ๋ ์ต๋ logn ์ํ
- ๊ฐ ํธ๋ฆฌ๊ฐ ์์ ์ ๋ฟ์ ์๋ ๋ชจ๋ ๊ฐ์ ์ ๊ฒ์ฌํ์ฌ ์ต์ ๊ฐ์ค์น๋ฅผ ๊ฐ์ง ๊ฐ์ ์ ์ ํํ๋ฏ๋ก O(m)์๊ฐ ์์
- ์ด ์ํ ์๊ฐ์ O(mlogn)