修路问题
一个小镇有一些房子和一些路,每条路连接且仅连接2座房子,连接u和v房子的路的维修代价为w(u,v),
现在要维修仅够需求的道路,使得:每两座房子之间保持连通,维修代价最小。
图为连通无向图,顶点为房子,边为路,维修费用为边的权。
找到一个T,T为E的子集,并且w(T)= ∑ ( u , v ) ∈ T w ( u , v ) \displaystyle \sum_{(u,v)∈T}w(u,v) (u,v)∈T∑w(u,v)
最小生成树特性
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安全的边?
一些定义:
定理:
A是MST的子集, (S, V - S)是不干预A的一个切割, (u, v)是横跨该切割的轻边,那么, (u, v)对于A是安全的。
Kruskal算法
不相关集合的操作
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
运行开销: O ( E l g V ) O(ElgV) O(ElgV)
Prim算法
如何快速确定LE?
利用优先队列
Prim(V,E,w,r)
Q ← 空集
for each u ∈ V
do key[u] ← ∞ \infty ∞
π[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)
参考:任课教师邱德红教授的课件