代碼:code
#include <stdio.h> //鬧了好長時間才鬧好,若是有不懂的地方能夠留言 //裏面判斷環的地方用到並查集 //並查集資料:<a target="_blank" href="http://dongxicheng.org/structure/union-find-set/">http://dongxicheng.org/structure/union-find-set/</a> #define ENUM 15//邊的數量 #define VNUM 9//頂點的數量 #define MV 0 typedef struct _tag_Edge //存儲邊的信息 { int begin; int end; int weight;//權值 }Edge; int father[VNUM]; //存儲 int son[VNUM]; int Matvix[VNUM][VNUM]= {//圖 {0, 10, MV, MV, MV, 11, MV, MV, MV}, {10, 0, 18, MV, MV, MV, 16, MV, 12}, {MV, 18, 0, 22, MV, MV, MV, MV, 8}, {MV, MV, 22, 0, 20, MV, 24, 16, 21}, {MV, MV, MV, 20, 0, 26, MV, 7, MV}, {11, MV, MV, MV, 26, 0, 17, MV, MV}, {MV, 16, MV, 24, MV, 17, 0, 19, MV}, {MV, MV, MV, 16, 7, MV, 19, 0, MV}, {MV, 12, 8, 21, MV, MV, MV, MV, 0}, }; void swap(Edge array[], int i, int j) { Edge temp = array[i]; array[i] = array[j]; array[j] = temp; } void SelectionSort(Edge array[], int len) // O(n*n) { int i = 0; int j = 0; int k = -1; for(i=0; i<len; i++) { k = i; for(j=i; j<len; j++) { if( array[j].weight < array[k].weight ) { k = j; } } swap(array, i, k); } } int unionsearch(int x) //查找根結點+路徑壓縮 { if(x != father[x]) {//經過遞歸找到根結點,注意邊最終的end爲根結點 father[x] = unionsearch(father[x]); } //father[x]爲x的父結點 return father[x]; } int join(int x, int y) //合併 { int root1, root2; root1 = unionsearch(x); root2 = unionsearch(y); if(root1 == root2) //爲環 return 0; else { //root2爲root1的父結點 father[root1] = root2; son[root2] += son[root1]; } return 1; } int main() { int i, j;//要使用的循環變量 int total = 0;//最後選出邊的數量 int sum = 0;//最後總權值 int flag = 0; int eNUM = ENUM-1; Edge array[ENUM];//總共的邊 for(i=0; i<VNUM; ++i) //初始化 { father[i] = i; son[i] = 1; } for(i=0; i<VNUM; i++) { for(j=0; j<VNUM; j++) { if((i<j) && (0 < Matvix[i][j])) {//給邊的結構體初始化 array[eNUM].begin = i; array[eNUM].end = j; array[eNUM--].weight= Matvix[i][j]; } } } //排序 ,對邊按照權值排序,從小到大 SelectionSort(array, ENUM); for(i=0; i<ENUM; i++) { if(join(array[i].begin, array[i].end)) {//判斷是否成環 total++; //邊數加1 sum += array[i].weight; //記錄權值之和 printf("%d -> %d weight:%d\n", array[i].begin, array[i].end, array[i].weight); } if(total == VNUM-1) //最小生成樹條件:邊數=頂點數-1 { flag = 1; break; } } if(flag) printf("%d\n", sum); else printf("error.\n"); return 0; }