๐Ÿ“Œ About

kruskal algorithm gif.gif

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์ด ํ˜•์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค.

๐Ÿ“Œ Algorithm

Step 1. E๊ฐœ์˜ ๊ฐ„์„ ๋“ค์„ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ํƒ์ƒ‰ํ•œ๋‹ค.

Step 2. ํƒ์ƒ‰ํ•œ ๊ฐ„์„  ์–‘๋ ์ •์ ์˜ root ์ •์ ์„ ํ™•์ธํ•œ๋‹ค.

Step 3. ๋‘ ์ •์ ์˜ root ์ •์ ์ด ๋‹ค๋ฅด๋ฉด union ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ฐ„์„ ์„ MST์— ์ถ”๊ฐ€ํ•œ๋‹ค.

Step 3-1. ๊ฐ„์„  ์ •๋ณด๋ฅผ MST์— ์ถ”๊ฐ€ํ•œ๋‹ค.

Step 3-2. ๊ฐ ์ •์ ์˜ root ์ •์ ์„ ํ™•์ธํ•œ๋‹ค.

๐Ÿ“Œ Java Code

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);
    }
}

๐Ÿ“Œ Example

๋‹ค์Œ๊ณผ ๊ฐ™์€ graph๊ฐ€ ์žˆ๋‹ค.

Untitled

Step 1. ๊ฐ„์„ ๋“ค์„ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ํƒ์ƒ‰ํ•œ๋‹ค.

Vertex 1 - Vertex 2 - Weight 1

Vertex 2 - Vertex 3 - Weight 2

Vertex 3 - Vertex 1 - Weight 3

Untitled

์ •์  1์˜ ๋ฃจํŠธ๋Š” 1์ด๋‹ค.

์ •์  2์˜ ๋ฃจํŠธ๋Š” 2์ด๋‹ค.

๋ฃจํŠธ๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— MST์— ์ถ”๊ฐ€ํ•œ๋‹ค.

์ •์  2์˜ ๋ฃจํŠธ๋ฅผ 1๋กœ ํ•œ๋‹ค.