第七章 图
7.4 (连通网的)最小生成树
问题:
假设要在 n 个城市之间建立通讯联络网,则连通 n 个城市只需要修建 n-1条线路,如何在最节省经费的前提下建立这个通讯网?
该问题等价于: 构造网的一棵最小生成树,即: 在 e 条带权的边中选取 n-1 条边(不构成回路),使“权值之和”为最小。
算法一:(普里姆算法)
算法二:(克鲁斯卡尔算法)
普里姆算法的基本思想:
假设N={V,{E})是连通网,TE是N上最小生成树边的集合。算法从U={u0}(u0∈V),TE={ }开始,重复执行下述操作:在所有u∈V,v∈V-U的边(u,v)∈E中找一条代价最小的边( u0,v0)并入集合TE,同时v0并入U,直至U=V为止。此时TE中必有n-1条边,则T=(V,{TE})为N的最小生成树。
一般情况下所添加的顶点应满足下列条件:
在生成树的构造过程中,图中 n 个顶点分属两个集合:已落在生成树上的顶点集 U 和尚未落在生成树上的顶点集V-U ,则应在所有连通U中顶点和V-U中顶点的边中选取权值最小的边。
例如:
所得生成树权值和= 14+8+3+5+16+21 = 67
设置一个辅助数组,对每个顶点,记录从顶点集U到V-U具有代价最小的边:
struct {
VertexType adjvex; // U集中的顶点
VRType lowcost; // 边的权值
} closedge[MAX_VERTEX_NUM];
void MiniSpanTree_P(MGraph G, VertexType u) {
//用普里姆算法从顶点u出发构造网G的最小生成树
k = LocateVex ( G, u );
for ( j=0; j<G.vexnum; ++j ) // 辅助数组初始化
if (j!=k)
closedge[j] = { u, G.arcs[k][j].adj };
closedge[k].lowcost = 0; // 初始,U={u}
for (i=0; i<G.vexnum; ++i) {
}
k = minimum(closedge);
// 求出加入生成树的下一个顶点(k)
printf(closedge[k].adjvex, G.vexs[k]);
// 输出生成树上一条边
closedge[k].lowcost = 0; // 第k顶点并入U集
for (j=0; j<G.vexnum; ++j)
//修改其它顶点的最小边
if (G.arcs[k][j].adj < closedge[j].lowcost)
<