原理理解及代码出处:Kruskal
中间的qsort()是自带的快速排序,不知道的请通往这里:qsort
并且顶点的合并等涉及到并查集的知识,不知道的请往这里走:并查集
整理后的代码如下:
#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; int parent[10]; //存储各节点的前驱节点的数组 int n,m; int i,j; //存储边的信息 struct edge { int u,v,w; //边的顶点,权值 } edges[10]; //初始化并查集 void UFset() { for(i=1; i<=n; i++) parent[i] = -1; //表示该节点的前驱节点就是本身 } //查找i的跟节点 int find(int i) { int temp; //查找位置 for(temp = i; parent[temp] >= 0; temp = parent[temp]); //压缩路径 while(temp != i) { int t = parent[i]; parent[i] = temp; i = t; } //返回根节点位置? return temp; } //合并两个元素a,b void merge(int a,int b) { int r1 = find(a); int r2 = find(b); int tmp = parent[r1] + parent[r2]; //两个集合节点数的和,二者之和为负数 if(parent[r1] > parent[r2]) { parent[r1] = r2; parent[r2] = tmp; } else { parent[r2] = r1; parent[r1] = tmp; } } void kruskal() { int sumWeight = 0; //记录代价 int num = 0; //记录合并次数 int u,v; //存放边连接的两个点 UFset(); //一直循环到各条边都遍历到了 for(int i=0; i<m; i++) { u = edges[i].u; v = edges[i].v; if(find(u) != find(v)) //u和v不在一个集合 { printf("加入边:%d %d,权值: %d\n", u,v,edges[i].w); sumWeight += edges[i].w; //加上该边的权值 num ++; merge(u, v); //把这两个边加入一个集合 //当n个节点经过n-1次合并后代表点都在一个集合中了,故算法结束 if(num==n-1) break; } } printf("weight of MST is %d \n", sumWeight); } //比较函数,用户排序 int cmp(const void * a, const void * b) { return ((*(edge*)a).w)-((*(edge*)b).w); /* 分开即为: edge * e1 = (edge *)a; edge * e2 = (edge *)b; return e1->w - e2->w; */ } int main() { //输入顶点数和边数 scanf("%d %d", &n, &m); //输入各条边的信息 for(i=0; i<m; i++) { scanf("%d %d %d", &edges[i].u, &edges[i].v, &edges[i].w); } //从小到大快排边 qsort(edges, m, sizeof(edge), cmp); kruskal(); return 0; } /* 如果要把数据储存下来则用数组各加入边再用邻接矩阵构造函数构造即可 */ /* 测试数据: 7 9 1 2 28 1 6 10 2 3 16 2 7 14 3 4 12 4 5 22 4 7 18 5 6 25 5 7 24 输出: 加入边:1 6,权值: 10 加入边:3 4,权值: 12 加入边:2 7,权值: 14 加入边:2 3,权值: 16 加入边:4 5,权值: 22 加入边:5 6,权值: 25 weight of MST is 99 */
有问题或有更好的请指出,请带着我一起进步。