算法设计与分析课程复习笔记10——最小生成树
最小生成树MST
修路问题
一个小镇有一些房子和一些路,每条路连接且仅连接2座房子,连接u和v房子的路的维修代价为w(u,v),
现在要维修仅够需求的道路,使得:每两座房子之间保持连通,维修代价最小。
图为连通无向图,顶点为房子,边为路,维修费用为边的权。
找到一个T,T为E的子集,并且w(T)=
最小生成树特性
- 非唯一
- 没有回路
- MST边的数目为顶点数目减1
MST生成
一般方法:
创建一个边的集合A,起始时为空
逐渐向A中添加边并保持A属于某个MST
当且仅当A ∪ {(u, v)}是MST的子集,我们说边(u, v)对于A是安全的
MST一般算法
A ← 空集
while A is not a spanning tree(没有形成生成树)
do find an edge(u,v) that is safe for A(寻找对A安全的边(u, v))
A ← A ∪ {(u,v)}
return A
如何找到对A安全的边?
一些定义:
- 切割:将图的顶点分成两个互不相连的两个集合S和V – S
- 如果一个边的两个端点分别在切割的两个集合S和V - S中,我们说该边横跨该切割
- 一个切割不干预集合A 集合A中没有边与该切割相交
- 横跨切割的轻边 所有横跨切割的边中权值最小的边
定理:
A是MST的子集, (S, V - S)是不干预A的一个切割, (u, v)是横跨该切割的轻边,那么, (u, v)对于A是安全的。
Kruskal算法
- 从每个顶点开始,每个顶点即是个组件
- 通过选择轻边LE,不断的将两个组件连接起来
- 依权值递增顺序检查边的集合
- 利用不相关集合的数据结构判断边是否连接不同的组件
不相关集合的操作
- MAKE-SET(u)创建集合,仅含元素u
- FIND-SET(u)包含u,返回代表元素
- 集合的任何元素具有某个特定的属性
- 集合
的特性是按字母顺序的第一个字母
E.g.: = {r, s, t, u},FIND-SET(u) = r,FIND-SET(s) = r - 对于给定的集合,返回同样的值
- UNION(u,v)合并操作
E.g.: = {r, s, t, u}, = {v, x, y}
UNION (u, v) = {r, s, t, u, v, x, y}
Kruskal(V,E,w)
A ← 空集
for each vertex v ∈ V
do MAKE-SET(v)
sort E into non-decreasing order by weight w(权值递增排序)
for each (u, v) taken from the sorted list
do if FIND-SET(u) ≠ FIND-SET(v) (属于不同的组件)
then A ← A ∪ {(u, v)}
UNION(u, v)
return A
运行开销:
Prim算法
- 集合A中的边形成一棵树
- 从任意选定的根开始
- 每次
- 确定切割( , V - )的LE
- 将LE加入A
- 重复直到树包含所有顶点
- 贪婪策略:每次加入的边使树的边的权值和增加最小
如何快速确定LE?
利用优先队列
- 包含所有不在树中的顶点(V – )
- 每个顶点赋予一个关键值,即树中连接至v的任何边(u, v)的最小权值
如果v与 任何的顶点不相连,则关键值为
增加节点后,所有与之相连的节点的关键值要做调整
Prim(V,E,w,r)
Q ← 空集
for each u ∈ V
do key[u] ←
π[u] ← NIL
key[r] ←0
Q ← V
while Q ≠ 空集
do u ← EXTRACT-MIN(Q)
for each v ∈ Adj[u]
do if v ∈ Q and w(u, v) < key[v]
then π[v] ← u
key[v] ← w(u, v)
算法分析
参考:任课教师邱德红教授的课件