最小生成树

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。

在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,w(T) 最小,则此 T 为 G 的最小生成树。最小生成树其实是最小权重生成树的简称。

在很多场景下有应用,例如:
网络G表示n各城市之间的通信线路网线路(其中顶点表示城市,边表示两个城市之间的通信线路,边上的权值表示线路的长度或造价。可通过求该网络的最小生成树达到求解通信线路或总代价最小的最佳方案。

1. prim算法

以某个顶点为起点生成最小生成树,每次将与生成树距离最小的顶点加入树,直到所有顶点加入生成树。此时所有边的权重和即为最小生成树的权重和。


在这里插入图片描述


代码实现思路:

mark[ i ] 表示顶点i是否在生成树内, min[ i ]表示顶点 i 到生成树相连的最小边权重,初始值为正无穷, SUM表示最小生成树的权值之和,初始值为0。

1.以v0为生成树起点,故使得mark[0] = true; min[0] = 0;
2.遍历v0的邻接表,将各顶点与v0的边权重赋给对应min[ i ]。
3.将权重最小的顶点vi加入生成树, mark[i] = true, SUM += min[i]
4.遍历vi的邻接表,如果顶点没加入生成树且该顶点与vi的边权重小于原min[i],则将新min赋给对应min[ i ]
5.重复3~4直到所有顶点进入最小生成树,返回SUM。

min[ i ] 可以用最小索引优先队列实现功能。

2. Kruskal算法

按照边的权重从小到大,将边加入最小生成树中,使用并查集保证加入的边不会与已经加入最小生成树的边构成环,直到树中含有V-1条边为止。

Prim算法是一条边一条边的构造最小生成树,每一步都为一棵树添加一条边。kruskal算法构造最小生成树的时候也是一条边一条边地构造,但它的切分规则是不一样的。它每一次寻找的边会连接一片森林中的两棵树。如果一副加权无向图由V个顶点组成,初始化情况下每个顶点都构成一棵独立的树,则V个顶点对应V棵树,组成一片森林,kruskal算法每一次处理都会将两棵树合并为一棵树,直到整个森林中只剩一棵树为止。

实现思路:
1.使用索引最小优先队列存储图中所有的边,每次使用取出权重最小的边
2.得到该边关联的两个顶点v和w,使用并查集判断v和w是否已经连通
3.如果不连通,则通过uf.connect(v,w)把顶点v所在的树和顶点w所在的树合并成一棵树,并把这条边加入到mst队列中
4.最终mst中存储的就是最小生树的所有边。


在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值