Kruskal algorithm์ ๋ํด์ ์ค๋ช ํ๊ธฐ ์ ์ spanning tree์ ๋ํด์ ์ฐ์ ์์์ผ ํ๋ค. Spanning tree๋ graph์ ์ต์ ์ฐ๊ฒฐ ๋ถ๋ถ ๊ทธ๋ํ๋ก ๊ฐ์ ์ ์๊ฐ ๊ฐ์ฅ ์ ๊ธฐ ๋๋ฌธ์ V๊ฐ์ ์ ์ ์ด ์๋ค๋ฉด ์ ์ E = V - 1์ด ๋๋ค. ๋ํ graph ๋ด์์ ์ฌ์ดํด์ ํ์ฑํ๋ฉด ์๋๋ค. ์ฌ๊ธฐ์ MST๋ผ๋ ๊ฐ๋ ์ด ๋์ค๋๋ฐ ์ด๋ spanning tree ์ค์์๋ ๊ฐ์ค์น์ ํฉ์ด ๊ฐ์ฅ ์ ์ ๊ฒ์ ์๋ฏธํ๋ค.
Kruskal algorithm์ MST๋ฅผ ๊ตฌํ๊ธฐ ์ํ algorithm์ด๋ค. Graph์ ๊ฐ์ ๋ค์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ณ ์ฐจ๋ก๋๋ก graph์ ์ถ๊ฐํ๋ค. ์ด ๋ ์ถ๊ฐ๋๋ ๊ฐ์ ๋๋ฌธ์ cycle์ด ํ์ฑ๋๋ฉด ํด๋น ๊ฐ์ ์ ์ถ๊ฐํ์ง ์๋๋ค.
Cycle์ ์ด๋ฃจ๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ์ union-find๋ฅผ ์ด์ฉํ๋ ๊ฒ์ด๋ค. ์ด๋ ์งํฉ์ ์ฌ์ฉํ๋ ๊ฒ์ธ๋ฐ ์ฒ์์๋ ๋ชจ๋ ์ ์ ์ด ์์ ์ผ๋ก๋ง ์ด๋ฃจ์ด์ง ์งํฉ์ ์ํ๋ค. ๋ํ ๊ฐ๊ฐ์ ์งํฉ์ ํฌํจ๋ ์์๋ค ์ค์ ํ๋์ ์ ์ ์ root์ผ๋ก ํ๋ค. ํ๋์ ๊ฐ์ (๋ ๊ฐ์ ์ ์ )์ cycle ์์ฑ ์ฌ๋ถ๋ฅผ ํ๋จํ ๋ ๋ ์ ์ ์ด ํฌํจ๋ ์งํฉ์ root๋ฅผ ํ์ธํ๋ค. ํ์ธํ ๋ root๊ฐ ๊ฐ์ผ๋ฉด ๋ ์ ์ ์ ๊ฐ์ ์งํฉ์ ์๋ ๊ฒ์ด๊ณ ๊ฐ์ ์ ํฌํจํ์ ๋ cycle์ด ํ์ฑ๋๋ค. ๋ฐ๋๋ก root๊ฐ ๋ค๋ฅด๋ฉด ๋ค๋ฅธ ์งํฉ์ ์ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ ์ ์ถ๊ฐํ์ฌ๋ cycle์ด ํ์ฑ๋์ง ์๋๋ค.
Step 1. E๊ฐ์ ๊ฐ์ ๋ค์ ์ค๋ฆ์ฐจ์์ผ๋ก ํ์ํ๋ค.
Step 2. ํ์ํ ๊ฐ์ ์๋ ์ ์ ์ root ์ ์ ์ ํ์ธํ๋ค.
Step 3. ๋ ์ ์ ์ root ์ ์ ์ด ๋ค๋ฅด๋ฉด union ํจ์๋ฅผ ํตํด ๊ฐ์ ์ MST์ ์ถ๊ฐํ๋ค.
Step 3-1. ๊ฐ์ ์ ๋ณด๋ฅผ MST์ ์ถ๊ฐํ๋ค.
Step 3-2. ๊ฐ ์ ์ ์ root ์ ์ ์ ํ์ธํ๋ค.
public class Kruskal {
private final Queue<Edge> edges
= new PriorityQueue<>(Comparator.comparingInt(o -> o.weight));
private final Map<Vertex, Vertex> roots = new HashMap<>();
private final Map<Vertex, Map<Vertex, Integer>> graph = new HashMap<>();
public Kruskal(List<Vertex> vertices, List<Edge> edges) {
this.edges.addAll(edges);
for (Vertex vertex : vertices) {
roots.put(vertex, vertex);
graph.put(vertex, new HashMap<>());
}
}
public Map<Vertex, Map<Vertex, Integer>> run() {
selectEdgesToMerge();
return graph;
}
private void selectEdgesToMerge() {
while (!edges.isEmpty()) {
Edge edge = edges.poll();
if (find(edge.vertexA).equals(edge.vertexB)) {
graph.get(edge.vertexA).put(edge.vertexB, edge.weight);
graph.get(edge.vertexB).put(edge.vertexA, edge.weight);
union(edge.vertexA, edge.vertexB);
}
}
}
private void union(Vertex vertexA, Vertex vertexB) {
vertexA = find(vertexA);
vertexB = find(vertexB);
if (vertexA.value < vertexB.value) roots.put(vertexB, vertexA);
else roots.put(vertexA, vertexB);
}
private Vertex find(Vertex vertex) {
Vertex root = roots.get(vertex);
return root.equals(vertex) ? vertex : find(root);
}
}
๋ค์๊ณผ ๊ฐ์ graph๊ฐ ์๋ค.
Step 1. ๊ฐ์ ๋ค์ ์ค๋ฆ์ฐจ์์ผ๋ก ํ์ํ๋ค.
Vertex 1 - Vertex 2 - Weight 1
Vertex 2 - Vertex 3 - Weight 2
Vertex 3 - Vertex 1 - Weight 3
์ ์ 1์ ๋ฃจํธ๋ 1์ด๋ค.
์ ์ 2์ ๋ฃจํธ๋ 2์ด๋ค.
๋ฃจํธ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ MST์ ์ถ๊ฐํ๋ค.
์ ์ 2์ ๋ฃจํธ๋ฅผ 1๋ก ํ๋ค.