代码: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; }