--- tags: Data structure and algorithm --- # Graph -- Spanning Tree ## Relative articles 1. [Graph -- Basic concept](https://hackmd.io/@Justin123/graph1) 2. [Graph -- Shortest path algorithm](https://hackmd.io/@Justin123/graph2) 3. [Graph – Spanning Tree](https://hackmd.io/@Justin123/graph3) (You're reading now!) ## Content 1. [Introduction](https://hackmd.io/MeHMqJ8rTou1sMCSzd9bmw?both#Introduction) 2. [Spanning tree](https://hackmd.io/MeHMqJ8rTou1sMCSzd9bmw?both#Spanning-Tree) 3. [Minimum spanning tree (MST)](https://hackmd.io/MeHMqJ8rTou1sMCSzd9bmw?both#Minimum-spanning-tree-MST) 4. [Algorithm for finding MST](https://hackmd.io/MeHMqJ8rTou1sMCSzd9bmw?both#Algorithm-for-finding-the-MST) 5. [Summary](https://hackmd.io/MeHMqJ8rTou1sMCSzd9bmw?both#Summary) 6. [Reference](https://hackmd.io/MeHMqJ8rTou1sMCSzd9bmw?both#Reference) ## Introduction Last time, we talked about how to find shortest path. Today, we're going to discuss a similar issue -- find the minimun spanning tree. ## Spanning Tree Given an undirected graph and using **|V| - 1 edges** to connect all the vertex, the result graph is spanning tree. ==Tree is a graph without loop inside==. Therefore, the spanning tree is a graph connect all the vertex without any loop in it. ```graphviz graph test { // title labelloc="t"; label = "Original graph\n\n"; rankdir=LR; A -- B [label = "2"] B -- C [label = "5"] A -- C [label = "3"] C -- D [label = "9"] B -- D [label = "1"] B -- E [label = "10"] D -- E [label = "3"] } ``` ```graphviz graph test { // title labelloc="t"; label = "Spanning tree\n\n"; rankdir=LR; A -- B [label = "2"] B -- C [label = "5"] C -- D [label = "9"] D -- E [label = "3"] } ``` ## Minimum spanning tree (MST) If the graph possesses different weights, there exists at least **minimun spanning tree**. Here is some application of minimun spanning tree. * **Connect all villages** Suppose we have **A**, **B**, **C**, **D** and **E** villages. We want to find minimum cost to build the road from one village to another and each village should has a path to go to other village. ```graphviz graph test { // title labelloc="t"; label = "Cost for building the roads\n\n"; rankdir=LR; A -- B [label = "2"] B -- C [label = "5"] A -- C [label = "3"] C -- D [label = "9"] B -- D [label = "1"] B -- E [label = "10"] D -- E [label = "3"] } ``` Within the graph above, we know the minimun spanning tree is: ```graphviz graph test { // title labelloc="t"; label = "Minimum cost for building the roads\n\n"; rankdir=LR; A -- B [label = "2"] B -- D [label = "1"] D -- E [label = "3"] A -- C [label= "3"] } ``` Here is the constraints for finding MST: 1. We must use only edges **within the graph**. 2. We must use exactly **|V| - 1** edges. 3. We may **not use edges that produce a cycle**. ## Algorithm for finding the MST * **Prim** The idea in **Prim algorithm** is to use the **minimum the weight** to connect two **MST**. This seems to be too abstract to image. Let's see an example. ```graphviz graph test { // title labelloc="t"; label = "Two MST\n\n"; rankdir=LR; B -- D [label = "1"] D -- E [label = "3"] A -- C [label = "3"] } ``` If we want to find the MST of these nodes, we only have to connect the **minimum edge** from MST1 to MST2, namely, the edge from **A to B**. Therefore, the whole BST will be ```graphviz graph test { // title labelloc="t"; label = "MST for whole tree\n\n"; rankdir=LR; A -- C [label = "3"] B -- D [label = "1"] D -- E [label = "3"] A -- B [label = "2"] } ``` Let's define **$V$** to be the set of all the vertex, **$X$** to be the set of all the MST we have now, **$V - X$** be the set of all the vertex not in **$X$**. Now, we only have to start from one node, A, and we can find the MST of the whole graph. A is now the only element in set **$X$** and all the other vertex is in $V-X$. ```graphviz graph test { // title labelloc="t"; label = "Step 1\n\n"; rankdir=LR; B -- C [label = "5"] C -- D [label = "9"] B -- D [label = "1"] B -- E [label = "10"] D -- E [label = "3"] A [color="red"] } ``` The min edges from **$X$** to **$V - X$** is 2, then connect it and put **$B$** into **$X$** and remove **$B$** from **$V - X$**. ```graphviz graph test { // title labelloc="t"; label = "Step 2\n\n"; rankdir=LR; A -- B [label = "2"] C -- D [label = "9"] D -- E [label = "3"] A, B [color = "red"] } ``` The min edges from **$X$** to **$V - X$** is **$1$**, then connect it and put **D** into $X$ and remove **D** from **$V - X$**. ```graphviz graph test { // title labelloc="t"; label = "Step 3\n\n"; rankdir=LR; E A -- B [label = "2"] B -- D [label = "1"] C A, B, D[color = "red"] } ``` $weight(A, C)$ and $weight(D, E)$ are both the minimum edges from **$X$** to **$V - X$**, then pick whichever we want. ```graphviz graph test { // title labelloc="t"; label = "Step 4\n\n"; rankdir=LR; E A -- B [label = "2"] B -- D [label = "1"] A -- C [label = "3"] A, B, C, D[color = "red"] } ``` Final step. ```graphviz graph test { // title labelloc="t"; label = "Step 5\n\n"; rankdir=LR; D -- E [label = "3"] A -- B [label = "2"] B -- D [label = "1"] A -- C [label = "3"] A, B, C, D, E[color = "red"] } ``` Now, we find the MST of the graph. ```cpp= // Adjacent matrix int cost[number_of_vertex][number_of_vertex]; // The minimun weight in set X int mincost[number_of_vertex]; // Check whether vertex is in tree bool used[number_of_vertex] int prim() { // Init the distance and flag fill(mincost, mincost + number_of_vertex, INF_MAX); fill(used, used + number_of_vertex, false); // Set the first cost to 0 mincost[0] = 0; // Result for the MST int res = 0; while(true) { // The vertex going to check int start = -1; // Get the node from set V - X for (int i = 0; i < number_of_vertex; ++i) { if (!used[i] && (start == -1 || mincost[i] < mincost[start])) { start = i; } } // Finish building MST if (start == -1) break; // Add start to set X and add the cost to res used[start] = true; res += mincost[start]; // Update the mincost to set V - X for (int i = 0; i < number_of_vertex; ++i) { mincost[i] = min(mincost[i], cost[start][i]); } } return res; } ``` --- * **Kruskal** The approach that Kruskal adopted was: 1. Everytime find the **minimum edges** in the tree. 2. Check whether new edge will form the loop 3. If it does, drop it. Otherwise, **add it to set $X$**. Remove the edge from the container. 4. Back to step 1 </br></br> For example: ```graphviz graph test { // title labelloc="t"; label = "Example\n\n"; rankdir=LR; A -- B [label = "2"] B -- C [label = "5"] A -- C [label = "3"] C -- D [label = "9"] B -- D [label = "1"] B -- E [label = "10"] D -- E [label = "3"] } ``` So the edge container should be: ```graphviz graph g { node[shape = record fontsize=15]; rankdir=LR; a [label = "1\nB\-D"] b [label = "2\nA\-B"] c [label = "3\nA\-C"] d [label = "3\nD\-E"] e [label = "5\nB\-C"] f [label = "9\nC\-D"] g [label = "10\nB\-E"] a -- b b -- c c -- d d -- e e -- f f -- g } ``` First pick up $edge(B, D)$. ```graphviz graph test { // title labelloc="t"; label = "Step 1\n\n"; rankdir=LR; B -- D [label = "1"] } ``` ```graphviz graph g { node[shape = record fontsize=15]; rankdir=LR; b [label = "2\nA\-B"] c [label = "3\nA\-C"] d [label = "3\nD\-E"] e [label = "5\nB\-C"] f [label = "9\nC\-D"] g [label = "10\nB\-E"] b -- c c -- d d -- e e -- f f -- g } ``` Pick $edge(A, B)$. ```graphviz graph test { // title labelloc="t"; label = "Step 2\n\n"; rankdir=LR; A -- B [label = "2"] B -- D [label = "1"] } ``` ```graphviz graph g { node[shape = record fontsize=15]; rankdir=LR; c [label = "3\nA\-C"] d [label = "3\nD\-E"] e [label = "5\nB\-C"] f [label = "9\nC\-D"] g [label = "10\nB\-E"] c -- d d -- e e -- f f -- g } ``` Pick $edge(A, C)$. ```graphviz graph test { // title labelloc="t"; label = "Step 3\n\n"; rankdir=LR; A -- B [label = "2"] A -- C [label = "3"] B -- D [label = "1"] } ``` ```graphviz graph g { node[shape = record fontsize=15]; rankdir=LR; d [label = "3\nD\-E"] e [label = "5\nB\-C"] f [label = "9\nC\-D"] g [label = "10\nB\-E"] d -- e e -- f f -- g } ``` Pick $edge(D, E)$ ```graphviz graph test { // title labelloc="t"; label = "Step 4\n\n"; rankdir=LR; A -- B [label = "2"] A -- C [label = "3"] B -- D [label = "1"] D -- E [label = "3"] } ``` ```graphviz graph g { node[shape = record fontsize=15]; rankdir=LR; e [label = "5\nB\-C"] f [label = "9\nC\-D"] g [label = "10\nB\-E"] e -- f f -- g } ``` Pick $edge(B, C)$, but it will form the loop, then drop it. ```graphviz graph test { // title labelloc="t"; label = "Step 5\n\n"; rankdir=LR; A -- B [label = "2"] A -- C [label = "3"] B -- D [label = "1"] D -- E [label = "3"] } ``` ```graphviz graph g { node[shape = record fontsize=15]; rankdir=LR; f [label = "9\nC\-D"] g [label = "10\nB\-E"] f -- g } ``` For both $edge(C, D)$ and $edge(B, E)$ form the loop, then drop them both. The tree here is MST. ```graphviz graph test { // title labelloc="t"; label = "MST\n\n"; rankdir=LR; A -- B [label = "2"] A -- C [label = "3"] B -- D [label = "1"] D -- E [label = "3"] } ``` ```cpp= class Union { public: Union(int number_of_vertices) { parent = new int[number_of_vertices]; rank = new int[number_of_vertices]; // Init the structure for (int i = 0; i < number_of_vertices; ++i) { parent[i] = -1; rank[i] = 0; } } ~Union() { delete[] parent; delete[] rank; } int find(int x) { // If parent equal itself, then return it if (parent[x] < 0) { return x; } else { // return the find(parent[x]) return find(parent[x]) } } void unite(int x, int y) { // First find the tree root x = find(x); y = find(y); if (x == y) { // No need to update return ; } if (rank[x] < rank[y]) { // Add small rank to big rank parent[x] = y; } else { parent[y] = x; // increase 1 if rank are the same if (rank[x] == rank[y]) { rank[x]++; } } } bool same(int x, int y) { // If the parent are the same return true, else return false return find(x) == find(y); } private: int* parent; int* rank; } ``` ```cpp= // Struct for the edges struct edge { int u, v cost; } // For finding the parent int parent[number_of_vertices]; // For finding the rank of the tree int rank[number_of_vertices]; // Container for saving the edges edge es[number_of_edges]; // Key function for sorting bool comp(const edge& e1, const edge& e2) { return e1.cost < e2.cost; } int Kruskal() { // First sort the edges by their weights sort(es, es + number_of_edges, comp); // Form the union find uni = Union(number_of_vertices); // Init the result to 0 int res = 0; // Start find the edges for (int i = 0; i < number_of_edges; ++i) { // Pop out the first edges edge e = es[i]; // If won't form the circle if (!uni.same(e.u, e.v)) { // then unite them uni.unite(e.u, e.v); res += e.cost; } } // return the result return res; } ``` ## Summary In this session, we discuss what is spanning tree and how to find the minumum spanning tree. These three articles are all about graph. Thanks for reading! ## Reference 1. [培養與鍛鍊程式設計的邏輯腦 第二版](https://www.books.com.tw/products/0010616945?gclid=Cj0KCQjwoub3BRC6ARIsABGhnyamNtOnA0U1z3yzZeFonqM2HT7jnj1WZcRX8ArR1_KwV3YEgkkkPlIaAlCZEALw_wcB)