最小生成树的两种经典算法


Prim & Kruskal Algorithm

转自:https://blog.csdn.net/qq_36951116/article/details/83089039

问题引出:假设要在n个城市之间建立通信网,则连通n个城市只需要n-1条线路。这时自然会考虑一个问题:如何在最节省经费的前提下建立这个通信网?


MST(minimal spanning treeproblem)

可以用连通网来表示n个城市以及n个城市之间的通信线路,其中,网的顶点表示城市,边表示两城市之间的线路,赋予边权值表示开设相应线路的代价。

这个问题就是最小生成树问题:求解连通无向图的权最小的生成树

Prim & Kruskal Algorithm 是利用MST性质构造最小生成树的两种算法。Prim算法用于稠密图效果更好,Kruskal算法则更适用于稀疏图。

MST性质

设G=(V,E)是一个连通网络,U是顶点集V的一个真子集。若(u,v)是G中一条“一个端点在U中(例如:u∈U),另一个端点不在U中”的边(例如:v∈V-U),且(u,v)具有最小权值,则一定存在G的一棵最小生成树包括此边(u,v)。

证明略去,具体可参考: https://blog.csdn.net/s_j_huang/article/details/79447041

Prim algorithm

算法思路:从已选顶点所关联的未选边中找出权重最小的边,并且生成树不存在环。  

其中,已选顶点是构成最小生成树的结点,未选边是不属于生成树中的边。 

(普里姆算法与求最短路径的迪杰斯塔拉算法思想很类似)  

下面我们对下面这幅图求其最小生成树:

图1

假设我们从顶点v1开始,所以我们可以发现(v1,v3)边的权重最小,所以第一个输出的边就是:v1—v3=1,

图2

然后,我们要从v1和v3作为起点的边中寻找权重最小的边,首先了(v1,v3)已经访问过了,所以我们从其他边中寻找,发现(v3,v6)这条边最小,所以输出边就是:v3—-v6=4,

图3

然后,我们要从v1、v3、v6这三个点相关联的边中寻找一条权重最小的边,我们可以发现边(v6,v4)权重最小,所以输出边就是:v6—-v4=2,

图4

然后,我们就从v1、v3、v6、v4这四个顶点相关联的边中寻找权重最小的边,发现边(v3,v2)的权重最小,所以输出边:v3—–v2=5,

图5

然后,我们就从v1、v3、v6、v4,v2这2五个顶点相关联的边中寻找权重最小的边,发现边(v2,v5)的权重最小,所以输出边:v2—–v5=3,

图6

最后,我们发现六个点都已经加入到集合U了,我们的最小生成树建立完成。

Kruskal algorithm

算法思路: 
(1)将边按权值从小到大的顺序添加到新图中,保证添加的过程中不会形成环 
(2)重复上一步直到连接所有顶点,此时就生成了最小生成树。这是一种贪心策略。

将图中所有边按照权重的大小 从小到大一个一个按顺序组合成最小生成树,在组合过程新加入的边会导致生成树形成环,那这条边就舍弃,直到所有顶点都添加到生成树中为止。  

这里同样我们给出一个和Prim算法讲解中同样的例子,模拟克鲁斯卡算法生成最小生成树的详细的过程:

首先完整的图如下图:

图7

然后,我们需要从这些边中找出权重最小的那条边,可以发现边(v1,v3)这条边的权重是最小的,所以我们输出边:v1—-v3=1,

图8

然后,我们需要在剩余的边中,再次寻找一条权重最小的边,可以发现边(v4,v6)这条边的权重最小,所以输出边:v4—v6=2,

图9

然后,我们再次从剩余边中寻找权重最小的边,发现边(v2,v5)的权重最小,所以可以输出边:v2—-v5=3,

图10

然后,我们使用同样的方式找出了权重最小的边:(v3,v6),所以我们输出边:v3—-v6=4,

图11

好了,现在我们还需要找出最后一条边就可以构造出一颗最小生成树,但是这个时候我们有三个选择:(v1,V4),(v2,v3),(v3,v4),这三条边的权重都是5,首先我们如果选(v1,v4)的话,得到的图如下:

图12

我们发现,这肯定是不符合我们算法要求的,因为它出现了一个环,所以我们再使用第二个(v2,v3)试试,得到图形如下:

图13

我们发现,这个图中没有环出现,而且把所有的顶点都加入到了这颗树上了,所以(v2,v3)就是我们所需要的边,所以最后一个输出的边就是:v2—-v3=5.


文章作者: Hailong Gao
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Hailong Gao !
评论
  目录