最小生成树算法

生成树的概念

  • 若图是连通的无向图或强连通的有向图,则从其中任一顶点出发,调用一次 d f s dfs dfs或者 b f s bfs bfs后,可以系统的访问图中所有顶点。
  • 若图是有根的有向图 ,则从根出发,调用一次 d f s dfs dfs或者 b f s bfs bfs后,可以系统的访问图中所有顶点。

在上述情况之下,图中所有顶点加上遍历过程中经过的所有边所构成的子图称为原图的生成树

若图是不连通的的无向图和不是强连通的有向图,从其中任一顶点出发,调用一次 d f s dfs dfs或者 b f s bfs bfs后,不能系统的访问图中所有顶点,只能得到以出发点为根的连通分支(或者强连通分支)的生成树。若想访问其他顶点则需要以一个没有访问过的点作为起点,再次调用 d f s dfs dfs或者 b f s bfs bfs,这样就得到了生成森林

很显然,一个图的生成树并不是唯一的,不同的搜索方法或者同一个搜索方法但出发点不同,都可以得到不同的生成树。
可以证明:具有n个顶点的带权连通图,其对应的生成树有n-1条边。

最小生成树算法

举例:给出一张有五座城市的地图。
在这里插入图片描述
用DFS遍历得到的生成树:
在这里插入图片描述
用BFS遍历得到的生成树:
在这里插入图片描述
上述俩种生成树的权和分别为20和33,我们不难发现,最小的生成树权和应该为19,因此上述俩种并不是最小生成树。那如何得到最小生成树呢?
在这里插入图片描述
出发点:具有n个顶点的带权连通图,其对应的最小生成树都有n-1条边。
下列俩种算法都是基于贪心思想的算法。
时间复杂都为O(n*n)。

Prim算法

思路如下:

  1. 设置一个顶点集合S和一个边集合TE,S和TE的初始状态皆为空集。
  2. 选定图中的任意顶点K,从K开始生成最小生成树。(K加入集合S)。
  3. 重复下列操作,直到选取了n-1条边为止。
    (1)选取一条权最小的边(X,Y),要求是X要集合S的元素,Y不是集合S的元素。
    (2)将顶点加入到集合S中,将边(X,Y)加入集合TE中。
  4. 得到最小生成树T,T=(S,TE)。

Kruskal算法

思路如下:

  1. 设最小生成树为T,T=(S,TE),TE初始状态为空集。
  2. 将图中的边权从小到大依次排序。
  3. 选取权最小的边,若这条边没有使T构成回路,就将这条边加入TE中(T保留了这条边);若构成回路,则舍弃,不能加入TE中。
  4. 再选取最小边,重复执行第三步,直到TE中包含n-1条边为止,最后的T即为最小生成树。

这个算法的难点在于,在选取权最小的边后,如何判断该边有没有使T构成回路。这里推荐一种方法:

将n个顶点划分为n个集合,就是每个集合只有一个顶点,表明他们之间互不相同,各自为无回路的连通分支。当选取一条边后:

  • 若这条边俩个顶点不属于同一集合,则表明了改边连通了俩个不同的连通分支,又因为每个连通分支都是无回路的,所以连通俩个连通分支后,也无法形成回路,所以该边保留,作为T的一条边。然后把这条边的俩个顶点所在集合合并为一个集合,构成一个新的无回路的连通分支。
  • 若这条边俩个顶点不属于同一集合,则舍弃,因为同一个集合中的顶点是连通无回路的,若加入一条俩个顶点都属于本集合的边,必会形成回路
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值