图的应用
最小生成树
定义
对于 带权无向连通图 G = ( V, E ), G的所有生成树当中边的 权值之和最小 的生成树为G的 最小生成树(MST) 。
性质
1、最小生成树不一定唯一,即最小生成树的树形不一定唯一。当带权无向连通图G的各边权值不等时或G只有结点数减1条边时,MST唯一。
2、最小生成树的权值是唯一的, 且是最小。
3、最小生成树的边数为顶点数减1。
算法实现
Prim (普里姆)算法
算法思路
初始化:向空的结果树 T =(Vt,Et) 中添加图 G =(V, E) 的任一顶点u0,使 Vt = {u0},Et为空集;
循环(直到Vt = V):从图G中选择满足 { (u, v) | u∈Vt ,v∈ V-Vt }且具有最小权值的边(u,v),并置Vt = Vt U {v} , Et =Et U (u, v) }。
代码实现
辅助数组理解:
min_weight [n] :存放相关顶点间边的权值
表示最小生成树中已存放的顶点到未存放顶点的最小权值
例:假设有 v0,v1,v2,v3,v4 这5个顶点
min_weight [5] = {0, 2, 0, 0, 0} 表示最小生成树中已存放的顶点到顶点v1的最小权值是2
adjvex [n] :存放相关顶点的下标
例:假设有 v0,v1,v2,v3,v4 这5个顶点
adjvex [5] = {0, 0, 1, 0, 1} 表示顶点v2和顶点v4 这两个点和顶点v1间都有边
void MST_Prim(Graph G)
{
int min_weight[G.vexnum]; //存放相关顶点间边的权值
int adjvex[G.vexnum]; //存放相关顶点的下标
//初始化操作
for(int i = 0; i < G.vexnum; i++)
{
min_weight[i] = G.Edge[0][i]; //将邻接矩阵第0行所有权值加入数组
adjvex[i] = 0; //全部初始化为v0下标
}
//正式构造最小生成树的过程
int min_arc; //临时变量,表示当前最小权值
int min_vex; //临时变量,表示当前最小权值边的顶点数组下标
for(int i = 1; i < G.vexnum; i++) //由于有一个顶点已在最小生成树中,所以只遍历n-1次
{
min_arc = INT_MAX; //初始化最小权值为65535等不可能数值
for(int j = 1; j < G.vexnum; j++)
{
//找出min_weight[]数组中已存的最小权值
if(min_weight[j] != 0 && min_weight[j] < min_arc)
{
min_arc = min_weight[j];
min_vex = j; //将发现最小权值的下标存入min_vex, 待使用
}
}
min_weight[min_vex] = 0; //将当前顶点的权值设为0,表示此顶点已完成任务
//遍历全部顶点
for(int j = 0; j < G.vexnum; j++)
{
if(min_weight[j] != 0 && G.Edge[min_vex][j] < min_weight