最小生成树
参考《算法第四版》-Robert Sedgewick , Kevin Wayne, 谢路云译
1. 定义:
一幅加权图的最小生成树(MST)是它的一棵权值(树中所有边的权值之和)最小的生成树。
下图中用边的长度来表示边的权值大小,找最小生成树就是找出连通图中的边,让边的权值之和最小
2. 重要性质:
(1)用一条边连接树中的任意两个顶点都会产生一个新的环;
(2)从树中删去一条边将会得到两棵独立的树。
这两条性质是证明最小生成树的另一条基本性质的基础,而由这条基本性质就能够得到本节中的最小生成树算法。
(3)最小生成树的边数 = 顶点数-1
3. 切分定理
定义:图的一种切分是将图的所有顶点分为两个非空且不重叠的两个集合。横切边是一条连接两个属于不同集合的顶点的边。
切分定理:在一幅加权图中,给定任意的切分,它的横切边中的权重最小者必然属于图的最小生成树(反证法易证:否则能找到更小的权重边构建最小生成树):
在假设所有的边的权重均不相同的前提下,每幅连通图都只有一棵唯一的最小生成树。
4. Prim 算法
Prim 算法能够得到任意加权连通图的最小生成树。
基于贪心算法:每一步都会为一棵生长中的树添加一条边。一开始这棵树只有一个顶点,然后会向它添加 V-1 条边,每次总是将下一条连接树中的顶点与不在树中的顶点且权重最小的边(黑色表示)加入树中。
(1)常用数据结构
顶点:使用一个由顶点索引的布尔数组 marked[],如果顶点 v 在树中,那么 marked[v] 的值为 true;
边:选择以下两种数据结构之一:一条队列 mst 来保存最小生成树中的边,或者一个由顶点索引的 Edge 对象的数组edgeTo[],其中edgeTo[v] 为将v连接到树中的Edge对象;
横切边:使用一个优先队列来根据权重比较所有边。
(2)算法步骤
举个例子:求下面这个连通图的最小生成树
详细步骤:
步骤1 | 步骤2 | 步骤3 |
步骤4 | 步骤5 | 步骤6 |
步骤1:默认保留第0个顶点,找出它的边:7、5、7,加入横切边队列(红色数字):{7,5,7}
步骤2:找出横切边队列中最小的边,即5,标记相连的顶点2,将顶点2的边加入横切边队列:{7,5,7,3,4,8,6},为了减少横切边的个数(加速),将已保留的顶点间的边删去(灰色数字),此时,横切边队列为:{7,7,3,4,8,6}
步骤3: 找出横切边队列中最小的边,标记相连的顶点1,将顶点1的边加入横切边队列:将已保留的顶点间的边删去(灰色数字),此时,横切边队列为:{7,4,7,8,6}
步骤4、5、6相似,最后生成树如步骤6图所示