자료구조와 알고리즘/Graph

Prim's Minimum Spanning Tree (MST)

그레이트쪼 2016. 9. 13. 22:59

개요 

  • MST는 graph의 vertex들을 최소 비용으로 연결한 tree이다. 
  • Prim의 알고리즘도 Kruskal의 알고리즘과 마찬가지로 greedy 알고리즘이다. 그리고 같은 greedy 알고리즘인 Dijkstra와 알고리즘이 거의 유사하다.


방법

  • 두 개의 set을 유지한다. 첫 째는 이미 MST에 속한 vertex들, 두번 째는 여기에 포함되지 않은 녀석들. (즉, 두 set은 disjoint subset이다)
  • 그래서 알고리즘은 두 set간의 모든 edge 중에서 가장 짧은 녀석을 선택하는 것이다. 선택된 edge는 다시 MST에 포함된다. 
  • 그렇다면 두 set간의 edge는 어떻게 알 수 있나? 그것은 edge의 한쪽 vertex가 MST에 속하고 나머지 한쪽 vertex는 포함되지 않은 set에 있으면 된다. 

1) mstSet 만든다여기에 포함되는 vertex MST 이미 포함된 것들이다. 초기에는 당연히 empty set이다.

2) 그래프의 모든 vertex key 대입한다초기값은 INFINITE이다. 0 먼저 선택한다.

3) mstSet 모든 vertex 포함할 때까지

a) 포함되지 않는 node set 있는 녀석들  최소 key 가진 녀석 u 선택한다.

b) u mstSet 포함시킨다.

c) u 모든 이웃 vertex (adjacent vertices) key 값을 update한다기존key 보다 u-v edge값이  작으면 key값을 u-v edge값으로 바꾼다.



예제

  • 아래의 그래프를 예로 들어 보자.  

 


  • 모든 vertex의 key값은 INFINITE로 만든 뒤, 최초에 0을 mstSet에 집어넣는다. 그리고 0의 key값을 0으로 한다. 

 


  • 그런 다음, 0의 모든 이웃 노드들에 대해서 key 값을 갱신해주는데 기존에 가지고 있던 값보다 0과의 edge weight값이 작다면 그것으로 update한다. 여기서는 1과 7의 key값이 각각 4, 8로 갱신되었다.  

 


  • 가장 작은 key값을 가진 vertex를 선택하는데 여기서는 vertex 1 이다. 그리고 1의 이웃 노드 2의 key값을 8로 update한다.  

 


  • 가장 작은 key값을 가진 vertex가 2와 7인데 뭘 골라도 상관없으나 7을 선택하는 것으로 하겠다. 그리고 7의 이웃 노드 6과 8의 key값을 각각 1, 7로 update한다. 

 


  • 가장 작은 key값을 가진 vertex가 6을 선택하고 6의 이웃 노드 5과 8의 key값을 각각 2, 6로 update한다. 

 


  • 이와 같이 진행하면 결국 위와 같은 MST를 얻을 수 있다. 


Code

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
#include <stdio.h>
#include <limits.h>
  
// Number of vertices in the graph
#define V 5
  
// A utility function to find the vertex with minimum key value, from
// the set of vertices not yet included in MST
int minKey(int key[], bool mstSet[])
{
    // Initialize min value
    int min = INT_MAX, min_index;
  
    for (int v = 0; v < V; v++)
        if (mstSet[v] == false && key[v] < min)
            min = key[v], min_index = v;
  
    return min_index;
}
  
// A utility function to print the constructed MST stored in parent[]
int printMST(int parent[], int n, int graph[V][V])
{
    printf("Edge   Weight\n");
    for (int i = 1; i < V; i++)
        printf("%d - %d    %d \n", parent[i], i, graph[i][parent[i]]);
}
  
// Function to construct and print MST for a graph represented using adjacency
// matrix representation
void primMST(int graph[V][V])
{
    int parent[V]; // Array to store constructed MST
    int key[V];   // Key values used to pick minimum weight edge in cut
    bool mstSet[V];  // To represent set of vertices not yet included in MST
  
    // Initialize all keys as INFINITE
    for (int i = 0; i < V; i++)
        key[i] = INT_MAX, mstSet[i] = false;
  
    // Always include first 1st vertex in MST.
    key[0= 0;     // Make key 0 so that this vertex is picked as first vertex
    parent[0= -1// First node is always root of MST 
  
    // The MST will have V vertices
    for (int count = 0; count < V-1; count++)
    {
        // Pick thd minimum key vertex from the set of vertices
        // not yet included in MST
        int u = minKey(key, mstSet);
  
        // Add the picked vertex to the MST Set
        mstSet[u] = true;
  
        // Update key value and parent index of the adjacent vertices of
        // the picked vertex. Consider only those vertices which are not yet
        // included in MST
        for (int v = 0; v < V; v++)
  
            // graph[u][v] is non zero only for adjacent vertices of m
            // mstSet[v] is false for vertices not yet included in MST
            // Update the key only if graph[u][v] is smaller than key[v]
            if (graph[u][v] && mstSet[v] == false && graph[u][v] <  key[v])
                parent[v]  = u, key[v] = graph[u][v];
    }
  
    // print the constructed MST
    printMST(parent, V, graph);
}
  
  
// driver program to test above function
int main()
{
   /* Let us create the following graph
          2    3
      (0)--(1)--(2)
       |   / \   |
      6| 8/   \5 |7
       | /     \ |
      (3)-------(4)
            9          */
   int graph[V][V] = {{02060},
                        {20385},
                        {03007},
                        {68009},
                        {05790},
                       };
  
    // Print the solution
    primMST(graph);
  
    return 0;
}


  • 력값이다.

Edge   Weight

0 - 1    2

1 - 2    3

0 - 3    6

1 - 4    5

  • Time complexity는 O(V2)이다. 모든 노드에 대해서 이웃 노드들의 key값을 모두 갱신하기 때문이다. 만일 binary heap을 사용할 경우 O(E logV)로 줄일 수 있다.