本文主要参考自《算法》。
加权图是一种为每条边关联一个权值或是成本的图模型。这种图能够自然地表示许多应用。在一幅航空图中,边表示航线,权值则可以表示距离或是费用。在一幅电路图中,边表示导线,权值则可能表示导线的长度即成本,或是信号通过这条线路所需的时间。在这些情形中,最令人感兴趣的自然是将成本最小化。
图的生成树是它的一棵含有其所有顶点的无环连通子图。一幅加权图的最小生成树(Minimum Spanning Tree, MST)是它的一棵权值(树中所有边的权值之和)最小的生成树。
下方中我们主要叙述关于寻找无向图的最小生成树的两种经典算法:Prim & Kruskal。
原理
切分定理
我们先回顾一下树图(详细可参考博文图的概述)的两个最重要的性质:
1)用一条边连接树中的任意两个顶点都会产生一个新的环;
2)从树中删去一条边将会得到两棵独立的树。
我们称之为切分定理的这条性质将会把加权图中的所有顶点分为两个集合、检查横跨两个集合的所有边并识别哪条边应属于图的最小生成树。
图的一种切分是将图的所有顶点分为两个非空且不重叠的两个集合。横切边是一条连接两个属于不同集合的顶点的边。
《算法》中给出“切分定理”:在一幅加权图中,给定任意的切分,它的横切边中的权重最小者必然属于图的最小生成树。
如图1-1所示:
图1-1 切分定理
贪心算法
切分定理是解决最小生成树问题的所有算法的基础。更确切地说,这些算法都是一种贪心算法的特殊情况:使用切分定理找到最小生成树的一条边,不断重复直到找到最小生成树的所有边。这些算法相互之间的不同之处在于保存切分和判定权重最小的横切边的方式,但它们都是以下性质的特殊情况。
命题(最小生成树的贪心算法):下边这种方法会将含有V个顶点的任意加权连通图中属于最小生成树的边标记为黑色:初始状态下所有边均为灰色,找到一种切分,它产生的横切边均不为黑色。将它权重最小的横切边标记为黑色。反复,直到标记了V-1条黑色边为止。如下图1-2所示:
图1-2. 贪心最小生成树算法。该图显示了这个贪心算法运行的典型轨迹。每一幅图表现的都是一种切分,其中算法识别了一条权重最小的横切边(红色加粗)并将它加入最小生成树中。
加权无向图的表示
加权无向图如下图2-1所示:
图2-1 加权无向图表示
Prim
Prim算法可见于下图3-1:
图3-1 Prim算法的轨迹(延时实现)
《算法》中还提供另一个即时Prim的版本,在个人程序中没有实现。
Kruskal
Kruskal算法主要思想是按照边的权重顺序(从小到大)处理它们,将边加入最小生成树中(图中的黑色边),加入的边不会与已经加入的边构成环,直到树中含有V-1条边为止。这些黑色的边逐渐由一片森林合并为一棵树,也就是最小生成树。
Kruskal算法可见于下图4-1:
图4-1 Kruskal算法的轨迹
本文提到的两个算法的代码已托管至Github。