最小生成树(minimum spanning tree)问题的两种解法

最小生成树实际上就是最小连通图,找最小生成树就是找权值和最小连通图。

以下题为例:

城市公交网建设问题

【问题描述】

  有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权为在这两个城市之间修建高速公路的造价,研究后发现,这个地图有一个特点,即任一对城市都是连通的。现在的问题是,要修建若干高速公路把所有城市联系起来,问如何设计可使得工程的总造价最少?

【输入格式】

    n(城市数,1<=n<=100)

  e(边数)

  以下e行,每行3个数i,j,wij,表示在城市i,j之间修建高速公路的造价。

【输出格式】

  n-1行,每行为两个城市的序号,表明这两个城市间建一条高速公路。

【输入样例】

  5 8

  1 2 2

  2 5 9

  5 4 7

  4 1 10

  1 3 12

  4 3 6

  5 3 3

  2 3 8

【输出样例】

   1  2

   2  3

   3  4

   3  5

一.Prim算法

原理:

设G=(V,E)是一个有向连通图

U是顶点集V的一个子集

如果:

1、边(u,v) , u∈U且v∈(V-U),一个顶点在U中、另一个端点不在U中

2、(u,v)是满足条件1最小权值的边

那么

一定存在G的一棵最小生成树包含(u,v)

这是基本概念,由上证明可知,在(V-U)集合中,到U集合距离最小的点,必定在最小生成树中。因此该点到U的边必定在最小生成树中。

•          初始令U={v0}(v0 ÎV), TE={}

•          在所有uÎU, vÎV-U的边(u,v)ÎE中,找一条权最小的边(u0,v0)

•          将(u0,v0)并入集合TE,同时v0并入U

•          重复上述操作直至U等于V

•          T=(V,{TE})为N的最小生成树

如何表示集合U与集合V-U?

可以使用vis[]数组

vis[i]==1 表示在集合U中

vis[i]==0 表示在集合V-U中

 

如何来找符合条件边?

辅助数组:minn[]

minn[i]用于记录节点i到达点集U的最短权值

实际操作上会用到一点类似于“松弛”算法的思想,先将所有点距离U的距离定为正无穷,随意选一个点,进入U,将他周围的点更新,再遍历minn,找到最小边的点,将其加入U重复上述步骤直至U中包含所有点。

此外,我们还可以替换最小生成树的边来生成次小生成树,枚举相差的边,然后替换最小树中该边两端点路程中最长的那条边。

 

二.Kruskal

这种算法相对简单,复杂度也较低,主要运用了并查集的思想,使用连通分量判断(即father是否相同)

①    初始G(V, {}),即包含所有节点,边为空

 

①    将原图中所有的边按权值从小到大排序

 

①    从权值最小的边开始,如果这条边连接的两个节点于图G中不在同一个连通分量中,则添加这条边到图G中

 

①    重复3,直至图G中所有的节点都在同一个连通分量中

你可能感兴趣的:(最小生成树(minimum spanning tree)问题的两种解法)