Algorithm/DS, algorithms

Minimum Spanning Tree (MST) - Kruskal

Henu 2021. 5. 10. 00:38

크루스칼 알고리즘(Kruskal Algorithm)을 활용한 최소 스패닝 트리 구하기

모든 간선(Edge)에 대해 가중치가 가장 작은 간선부터 이어나가면서 최소 스패닝 트리를 구하는 알고리즘이다.

 

  • 유니온 파인드(Union-Find)에 대한 이해 8할
  • Edge 구조체 설계 2할?

find_topnode() 를 통해서 현재 정점(Vertax)최상단 노드(부모노드) 를 알 수 있다.

Node[Vertax]의 값이 음수이면 Vertax가 부모노드임을 의미한다

 

is_cycle()을 통해서 a와 b 정점이 서로 같은 노드인지 확인한다(find_topnode() 사용)

 

Union_node()를 통해서 a 와 b정점을 하나로 병합한다

a, b정점의 부모 노드가 가지는 값은 항상 음수이다.

값이 더 작을수록 더 많은 자식노드를 가지고 있는 것이므로 값이 작은쪽에 다른 노드의 값(음수)을 더해주고

반대편에는 값이 작은 노드의 정점번호를 넣어줘서 둘을 이어준다

글 진짜 못적네

 

 

Union Find Basic Code C++

Union Find를 이해하기 위한 기본 코드 findTopnode를 통해서 최상단 노드를 알 수 있다 union_node를 통해서 입력된 수의 최상단노드를 찾아 두 수를 연결해주는 작업을 한다 check_node를 통해서 두 수가

hyeo-noo.tistory.com

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// ------------------------------------------------------------------
//      최소 스패닝 트리
//      pseudo code
//      아래 사이트의 구현방식을 따름
//      https://www.cs.usfca.edu/~galles/visualization/Kruskal.html
//
//      2021/05/09
// ------------------------------------------------------------------
 
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
 
struct Line{
    int st;
    int ed;
    long long value;
};
 
int V, E;
long long result = 0;
int Node[10001];
vector<Line> Edge;
 
bool compare(Line &a, Line &b){
    return a.value < b.value;
}
 
int find_topnode(int a){
    if(Node[a] < 0return a;
    return find_topnode(Node[a]);
}
 
bool is_cycle(int a, int b){
    a = find_topnode(a);
    b = find_topnode(b);
    if(a == b) return true;
    else return false;
}
 
void Union_node(int a, int b){
    a = find_topnode(a);
    b = find_topnode(b);
    if(Node[a] > Node[b]){
        Node[b] += Node[a];
        Node[a] = b;
    }
    else{
        Node[a] += Node[b];
        Node[b] = a;
    }
}
 
void solve(){
    int va, vb, cnt = 0;
    for(int i = 0; i < Edge.size(); i++){
        if(cnt == V-1break;
        va = Edge[i].st;
        vb = Edge[i].ed;
        if(!is_cycle(va, vb)){
            Union_node(va, vb);
            result += Edge[i].value;
            cnt++;
        }
    }
    cout << result;
}
 
void init(){
    // test 1
    // 7 12
    // 1 2 3
    // 1 3 2
    // 3 2 1
    // 2 5 2
    // 3 4 4
    // 7 3 6
    // 5 1 5
    // 1 6 2
    // 6 4 1
    // 6 5 3
    // 4 5 3
    // 6 7 4
    // ans = 12
    
    int a, b, c;
    cin >> V >> E;
    for(int i = 0; i < E; i++){
        cin >> a >> b >> c;
        Edge.push_back({a, b, c});
    }
    sort(Edge.begin(), Edge.end(), compare);
    memset(Node, -1sizeof(Node));
}
 
int main(){
    init();
    solve();
    
    return 0;
}
cs

위와같은 basic code만 있으면 어느 문제든지 응용이 가능하다

 

Kruskal MST Visualzation

 

www.cs.usfca.edu

위 사이트에서 그래프를 여러번 돌려보며 구현했다