给定一个带权值的无向图,要求权值之和最小的生成树,常用的算法有Kruskal算法和Prim算法。这两个算法其实都是贪心思想的使用,但又能求出最优解。(代码借鉴http://blog.csdn.net/u014488381)
一.Kruskal算法
Kruskal算法的基本思想:先将所有边按权值从小到大排序,然后按顺序选取每条边,假如一条边的两个端点不在同一个集合中,就将这两个端点合并到同一个集合中;假如两个端点在同一个集合中,说明这两个端点已经连通了,就将当前这条边舍弃掉;当所有顶点都在同一个集合时,说明最小生成树已经形成。(写代码的时候会将所有边遍历一遍)
来看一个例子:
步骤:
(1)先根据权值把边排序:
AD 5
CE 5
DF 6
AB 7
BE 7
BC 8
EF 8
BD 9
EG 9
FG 11
(2)
选择AD这条边,将A、D加到同一个集合1中
选择CE这条边,将C、E加到同一个集合2中(不同于AD的集合)
选择DF这条边,由于D已经在集合1中,因此将F加入到集合1中,集合变为A、D、F
选择AB这条边,同理,集合1变为A、B、D、F
选择BE这条边,由于B在集合1中,E在集合2中,因此将两个集合合并,形成一个新的集合ABCDEF
由于E、F已经在同一集合中,舍弃掉BC这条边;同理舍弃掉EF、BD
选择EG这条边,此时所有元素都已经在同一集合中,最小生成树形成
象征性地舍弃掉FG这条边
实现代码如下:
#include <iostream> #include <cstring> #define MaxSize 20 using namespace std; struct Edge{ int begin; int end; int weight; }; struct Graph{ char ver[MaxSize + 1]; int edg[MaxSize][MaxSize]; }; void CreateGraph(Graph *g) { int VertexNum; char Ver; int i = 0; cout << "输入图的顶点:" << endl; while ((Ver = getchar()) != ' ') { g->ver[i] = Ver; i++; } g->ver[i] = '