Kruskal's MST Algorithm

신장트리(Spanning Tree)는 모든 vertex가 edge로 연결하면서 edge 사이에 사이클이 없는 그래프이다. vertex수는 edge수 + 1이 된다. 모든 vertex가 다 연결은 되어 있지만, 일부 edge를 사용하지 않아도 되는 점을 활용해 여러 문제를 해결할 수 있다. 예를 들어서 최소 비용으로 연결된 신장 트리를 찾을 때 사용할 수 있는데, 이것을 최소 신장 트리(Minimum Spanning Tree)라 한다.

크루스칼 알고리즘

대표적은 탐욕적 방법으로 최소 신장 트리 알고리즘이다.

동작 과정은 먼저 부모테이블을 만들어 자기 자신으로 부모로 초기화하고, 간선을 비용 오름차순으로 정렬하고 (sorted), 모든 정점을 방문할 때 까지 (for i in range(V)), 간선을 순서데로 확인하면서 사이클이 발생하는지 확인하고 (exist_cycle), 사이클이 발생하지 않을 경우만 부모테이블을 업데이트하여 트리에 포함시키고 (union) 이 과정을 반복 수행한다.

간선을 비용 오름차순으로 정렬한다.

edge2-30-30-20-11-3

cost

4

5

6

10

15

모든 정점을 방문할 때 까지 (for i in range(V)), 간선을 순서데로 확인하면서 사이클이 발생하는지 확인하고 (exist_cycle), 사이클이 발생하지 않을 경우만 트리에 포함시키고 (union) 이 과정을 반복 수행한다.

step 0

n: [0,1,2,3]
p: [0,1,2,3]
node0123

p[n]

0

1

2

3

step 1

union(2,3)
  find(2) -> 2
  find(3) -> 3 -> p[3] = 2
  p: [0,1,2,2]
node0123

p[n]

0

1

2

2

step 2

union(0,3)
  find(0) -> 0
  find(3) -> find(2) -> 2 -> p[2] = 0
  p: [0,1,0,2]
node0123

p[n]

0

1

0

2

step 3

union(0,2)
  find(0) -> 0
  find(2) -> 0 -> pass
node0123

p[n]

0

1

0

2

step 4

union(0,1)
  find(0) -> 0
  find(1) -> 1 -> p[1] = 0
  p: [0,0,0,2]
node0123

p[n]

0

0

0

2

코드

def kruskalMST(n, some_list):
    parent = []
    for i in range(n):
        parent.append(i)
    
    def find(parent, i):
        if parent[i] == i:
            return i
        else:
            parent[i] = find(parent, parent[i])
        return parent[i]
    
    def exsit_cycle(parent, n1, n2):
        n1 = find(parent, n1)
        n2 = find(parent, n2)
        
        if n1 == n2:
            return True
        else:
            return False
    
    def union(parent, n1, n2):
        n1 = find(parent, n1)
        n2 = find(parent, n2)
        if n1 <= n2:
            parent[n2] = n1
        else:
            parent[n1] = n2
        return parent
    
    some_list = sorted(some_list, key=lambda x: x[2])
    min_cost = 0
    for [n1, n2, w] in some_list:
        if not exsit_cycle(parent, n1, n2):
            min_cost += w
            parent = union(parent, n1, n2)
            print("{} -- {} == {}".format(n1, n2, w))
            print("parent: {}".format(parent))
            
    return min_cost

n = 4
some_list = [[0,1,10], [0,2,6], [0,3,5], [1,3,15], [2,3,4]]
min_cost = kruskalMST(n, some_list)
print("Minimum Spanning Tree: {}".format(min_cost))

참고자료

https://velog.io/@ming/MST최소-신장트리-알고리즘 https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/ https://github.com/chaminhye/Algorithm/blob/master/src/concept/graph/Kruskal.java https://deep-learning-study.tistory.com/592

Last updated