3.6.2 Kruskal’s algorithm (ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜)

2024. 2. 5. 15:13ใ†CS - Roadmap.sh/3. Common Algorithms

CS - 3. Common Algorithms - 3.6 Greedy Algorithms - 3.6.2 Kruskal's algorithm

Kruskal’s algorithm

๐Ÿ’กKruskal’s algorithm is a greedy algorithm that finds a minimum spanning tree for a connected weighted graph. It is a minimum spanning tree algorithm that takes a graph as input and finds the subset of the edges of that graph which form a tree that includes every vertex, where the total weight of all the edges in the tree is minimized. If the graph is not connected, then it finds a minimum spanning forest (a minimum spanning tree for each connected component).

ํฌ๋ฃจ์Šค์นผ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์—ฐ๊ฒฐ๋œ ๊ฐ€์ค‘ ๊ทธ๋ž˜ํ”„์— ๋Œ€ํ•œ ์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๋ฅผ ์ฐพ๋Š” ํƒ์š•์Šค๋Ÿฌ์šด ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค. ์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ทธ๋ž˜ํ”„๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„ ๋ชจ๋“  ์ •์ ์„ ํฌํ•จํ•˜๋Š” ํŠธ๋ฆฌ๋ฅผ ํ˜•์„ฑํ•˜๋Š” ๊ทธ๋ž˜ํ”„์˜ ๊ฐ€์žฅ์ž๋ฆฌ ๋ถ€๋ถ„ ์ง‘ํ•ฉ์„ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ, ํŠธ๋ฆฌ์— ์žˆ๋Š” ๋ชจ๋“  ๊ฐ€์žฅ์ž๋ฆฌ์˜ ์ด ๊ฐ€์ค‘์น˜๊ฐ€ ์ตœ์†Œํ™”๋˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜ํ”„๊ฐ€ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ตœ์†Œ ์ŠคํŒจ๋‹ ํฌ๋ฆฌ์ŠคํŠธ(์—ฐ๊ฒฐ๋œ ๊ฐ ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ)๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

 

 

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜(Kruskal's algorithm)์€

https://parkpakrsu.tistory.com/329

 

Data structures (with python) - 2. Graph - 2.3. Spanning Tree

Data structures (with python) - 2. Graph - 2.3. Spanning Tree Spanning Tree ๐Ÿ’ก A spanning tree is a subset of Graph G, which has all the vertices covered with minimum possible number of edges. Hence, a spanning tree does not have cycles and it cannot be

parkpakrsu.tistory.com

์—์„œ ํ•œ๋ฒˆ ๋‹ค๋ค˜์Šต๋‹ˆ๋‹ค.

 

์—ฐ๊ฒฐ๋œ ๊ฐ€์ค‘๊ทธ๋ž˜ํ”„์—์„œ ์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ(์ตœ์†Œ ์‹ ์žฅํŠธ๋ฆฌ, MST, Minimum Spanning Tree)๋ฅผ ์ฐพ๋Š” ํƒ์š•์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค.

 

ํ•œ๋ฒˆ๋” ๋‹ค๋ฃจ๊ณ  ๋„˜์–ด๊ฐ€์ž๋ฉด,

MST๋Š” ๊ทธ๋ž˜ํ”„ ๋‚ด์˜ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค.

์ฆ‰, ๊ทธ๋ž˜ํ”„์˜ ์ตœ์†Œ ์—ฐ๊ฒฐ ๋ถ€๋ถ„ ๊ทธ๋ž˜ํ”„์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ, ์‚ฌ์ดํด์ด ํฌํ•จ๋˜์–ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

 

์ฃผ๋กœ ํ†ต์‹ ๋„คํŠธ์›Œํฌ, ๋„๋กœ ๋„คํŠธ์›Œํฌ๋“ฑ ์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

 

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์›๋ฆฌ

 

๊ฐ„์„ ์„ ๊ฐ€์ค‘์น˜์˜ ์˜ค๋ฆ„์ฐจ์ˆœ ์œผ๋กœ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ๊ฐ€์ค‘์น˜๊ฐ€๋‚ฎ์€ ๊ฐ„์„ ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ์„ ํƒํ•˜๋˜, ์‚ฌ์ดํด์„ ํ˜•์„ฑํ•˜๋Š” ๊ฐ„์„ ์€ ์ œ์™ธ

์ด๋ฅผ ์œ„ํ•ด ์œ ๋‹ˆ์˜จ-ํŒŒ์ธ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

(์œ ๋‹ˆ์˜จ-ํŒŒ์ธ๋“œ Union-Find ๋Š” ๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๋‘ ๋…ธ๋“œ๊ฐ€ ๊ฐ™์€ ๊ทธ๋ž˜ํ”„์— ์†ํ•˜๋Š”์ง€ ํŒ๋ณ„ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค.)

 

In Python
class Graph:
    def __init__(self, vertices):
        self.V = vertices
        self.graph = []
	# ๊ทธ๋ž˜ํ”„๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
    # vertices๋Š” ๊ทธ๋ž˜ํ”„์˜ ์ •์ ์˜ ์ˆ˜
    # self.graph ๊ทธ๋ž˜ํ”„์˜ ๊ฐ„์„ ์„ ์ €์žฅํ•˜๋Š” ๋ฆฌ์ŠคํŠธ

    def add_edge(self, u, v, w):
        self.graph.append([u, v, w])
	# u, v ๋Š” ๊ฐ„์„ ์˜ ์–‘ ๋ ์ •์ 
    # w๋Š” ๊ฐ„์„ ์˜ ๊ฐ€์ค‘์น˜

    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])
	#fine(self, parent, i)์ด ๋ฉ”์„œ๋“œ์—์„œ ๋ถ€๋ชจ๋ฐฐ์—ด์˜ i ๋ฒˆ์งธ ์ •์ ์˜ ๋ฃจํˆฌ๋ฅผ ์ฐพ๋Š”๋‹ค.


    def union(self, parent, rank, x, y):
        xroot = self.find(parent, x)
        yroot = self.find(parent, y)
        if rank[xroot] < rank[yroot]:
            parent[xroot] = yroot
        elif rank[xroot] > rank[yroot]:
            parent[yroot] = xroot
        else :
            parent[yroot] = xroot
            rank[xroot] += 1
	# union ๋ฉ”์„œ๋“œ๋Š” ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ง‘ํ•ฉ์„ ํ•ฉ์นœ๋‹ค.
    # x, y๋Š” ๊ฐ๊ฐ ์ง‘ํ•ฉ์„ ๋Œ€ํ‘œํ•˜๋Š” ๋ฃจํŠธ ์ •์ 
    # ์ด ๋ฉ”์„œ๋“œ์—์„œ ๋‘ ์ง‘ํ•ฉ์˜ rank๋ฅผ ๋น„๊ตํ•ด ๋žญํฌ๊ฐ€ ๋” ๋‚ฎ์€ ์ง‘ํ•ฉ์„ ๋žญํฌ๊ฐ€ ๋” ๋†’์€ ์ง‘ํ•ฉ์— ํ•ฉ์นœ๋‹ค.
    # ๋žญํฌ๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ํ•œ ์ง‘ํ•ฉ์„ ๋‹ค๋ฅธ ์ง‘ํ•ฉ์— ํ•ฉ์น˜๊ณ  ๋žญํฌ๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.


    def kruskal(self):
        result = []
        i = 0
        e = 0
        self.graph = sorted(self.graph, key=lambda item: item[2])
        parent = []
        rank = []
        for node in range(self.V):
            parent.append(node)
            rank.append(0)
        while e < self.V - 1:
            u, v, w = self.graph[i]
            i += 1
            x = self.find(parent, u)
            y = self.find(parent, v)
            if x != y:
                e += 1
                result.append([u, v, w])
                self.union(parent, rank, x, y)
        return result

 

 

 

 

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(E log E) ์ž…๋‹ˆ๋‹ค.

E ๋Š” edge๋กœ ๊ทธ๋ž˜ํ”„ ๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜์ž…๋‹ˆ๋‹ค.

 

์™œ O(E log E)์ผ๊นŒ์š”?

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์‹œ์ž‘ํ•  ๋–„ ๋ชจ๋“  ๊ฐ„์„ ์„ ๊ฐ€์ค‘์น˜์— ๋”ฐ๋ผ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ์ •๋ ฌ ๊ณผ์ •์ด ๊ฐ€์žฅ ์‹œ๊ฐ„์ด ๋งŽ์ด ๊ฑธ๋ฆฌ๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์ด๋ถ€๋ถ„์ด ๋ฐ”๋กœ O(E log E) ์‹œ๊ฐ„ ์ด ์†Œ์š”๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ๊ฐ ๊ฐ„์„ ์„ ์ˆœํšŒํ•˜๋ฉฐ ์‚ฌ์ดํด์„ ํ˜•์„ฑํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” ๊ฐ ๊ฐ„์„ ๋งˆ๋‹ค 'Find', 'Union' ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ํฌํ•จํ•˜๋Š”๋ฐ, ์ด ๋‘ ์—ฐ์‚ฐ์€ ๊ฑฐ์˜ ์ƒ์ˆ˜ ์‹œ๊ฐ„์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ O(E) ์‹œ๊ฐ„์ด ์†Œ์š”๋ฉ๋‹ˆ๋‹ค.

 

์ด O(E log E)์ด๋ฏ€๋กœ ๊ฐ„์„ ์ด ๋งŽ์€ ๋ฐ€์ง‘ ๊ทธ๋ž˜ํ”„์—์„œ๋„ ํšจ์œจ์ ์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

 

 

๋ฌธ์ œ

์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ - ๋ฐฑ์ค€ 1197

๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ - ๋ฐฑ์ค€ 1922

 

 

 

728x90