首页 > 代码库 > 关于最小生成树问题
关于最小生成树问题
我们通过一个例子来看一下最小生成树的求法。
分别用普里姆算法(从A结点开始)和克鲁斯卡尔算法计算下图的最小生成树。
ok,首先运用Prim算法进行计算:
U | V-U | B | C | D | E | F | TE |
{A} | {B,C,D,E,F} | AB 11 | AC 13 | ~ ∞ | AE 16 | ~ ∞ | AB 11 |
{A,B} | {C,D,E,F} | BC 7 | BD 3 | AE 16 | BF 5 | BD 3 | |
{A,B,D} | {C,E,F} | BC 7 | AE 16 | BF 5 | BF 5 | ||
{A,B,D,F} | {C,E} | BC 7 | FE 12 | BC 7 | |||
{A,B,D,F,C} | {E} | FE 12 | FE 12 | ||||
{A,B,D,F,C,E} | {} |
那么对照例图和表格我们就很容易地可以看出该算法的计算流程,首先从结点A开始,分别写出与其他结点的路径和权值,如果不连通则取权值为无穷,于是就有了表格的第二行,TE取代价最小的AB;然后将B添加到U,写出结点B与其他结点的路径和相应的权值,当然A就不用再写了,大家可以看到,凡是添加到最小生成树中的路径,之后该列则为空,因为它已经是代价最小的边,不可能再有其他边比它更小了;还有一个问题。为了方便起见,在同一列中,如果对应边的权值不小于其前一个,则将其直接落下来,这样就可以只比较那个“更小的”,这样就不用每一行都去比较了;按照这个思路,表格的第三行,BD的权值为3,小于其前一个的权值无穷,则写入3;第五行,FE的权值为12,小于其前一个AE的权值16,所以写入12;其实每一行和每一列都是在找那个代价最小的路径,这样求得的集合就是最小生成树,当然还得加入结点的集合,这样所示表格也就不难理解了,每一行找到一条代价最小的路径,加入TE,然后将结点加入U,再去比较其他的路径,就这样一直走下去,最后得到最小生成树集合。
接下来进入克鲁斯卡尔算法:
首先看一下它的基本思想:先构造一个只含 n 个顶点的子图 SG,然后从权值最小的边开始,若它的添加不使SG 中产生回路,则在 SG 上加上这条边,如此重复,直至加上 n-1 条边为止。一句话,“不构成环的情况下,每次选取最小边” 。它的出发点就是为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能地小。因此我们就从权值最小的边开始构造,前提是不构成环。
那么我们直接从图中找权值最小的边进行组合,首先是BD,然后是BF,BC,CF不行,因为其构成了环,AB可以,EF也可以,ok,这样就得到了最小生成树边的集合TE={BD,BF,BC,AB,EF},是不是比Prim算法简单的多?!
所以该图的最小生成树可以表示为T=({A,B,D,F,C,E},{BD,BF,BC,AB,EF}),当然最好还是可以画出图来,这样会更加直接明了。