Kruskal演算法求最小生成樹-演算法設計與分析實驗3
阿新 • • 發佈:2019-02-08
題目: 求如圖所示,用kruskal演算法求下面圖的最小生成樹:
話不多說,程式如下:
執行結果如下:#include<iostream> #include<stdlib.h> #define N 7 using namespace std; typedef struct _node{ int val; int start; int end; }Node; Node V[N]; int cmp(const void *a, const void *b) { return (*(Node *)a).val - (*(Node*)b).val; } int edge[N][3] = { { 0, 1, 3 }, { 0, 4, 1 }, { 1, 2, 5 }, { 1, 4, 4 }, { 2, 3, 2 }, { 2, 4, 6 }, { 3, 4, 7} }; int father[N] = { 0, }; int cap[N] = {0,}; void make_set() //初始化集合,讓所有的點都各成一個集合,每個集合都只包含自己 { for (int i = 0; i < N; i++) { father[i] = i; cap[i] = 1; } } int find_set(int x) //判斷一個點屬於哪個集合,點如果都有著共同的祖先結點,就可以說他們屬於一個集合 { if (x != father[x]) { father[x] = find_set(father[x]); } return father[x]; } void Union(int x, int y) //將x,y合併到同一個集合 { x = find_set(x); y = find_set(y); if (x == y) return; if (cap[x] < cap[y]) father[x] = find_set(y); else { if (cap[x] == cap[y]) cap[x]++; father[y] = find_set(x); } } int Kruskal(int n) { int sum = 0; make_set(); for (int i = 0; i < N; i++)//將邊的順序按從小到大取出來 { if (find_set(V[i].start) != find_set(V[i].end)) //如果改變的兩個頂點還不在一個集合中,就併到一個集合裡,生成樹的長度加上這條邊的長度 { Union(V[i].start, V[i].end); //合併兩個頂點到一個集合 sum += V[i].val; } } return sum; } int main() { for (int i = 0; i < N; i++) //初始化邊的資料,在實際應用中可根據具體情況轉換並且讀取資料,這邊只是測試用例 { V[i].start = edge[i][0]; V[i].end = edge[i][1]; V[i].val = edge[i][2]; } qsort(V, N, sizeof(V[0]), cmp); cout << Kruskal(0)<<endl; return 0; }
從圖中也可以看出,最小權值是: 1+3+5+2 = 11,那麼這個實驗的第一小題就是這樣。