使用贪心算法解决最小生成树

生成树的定义:对于一个图G,获取G的边使得全部的顶点都链接到。最小生成树(MST Minimun spanning tree):给定图G(V,E),以及对应的边的权重,获取一颗总权重最小的生成树。算法

树的定义:链接的无环图数据结构

直接策略

找到全部的生成树,而后计算权重最小的cors

考虑上面的图,一但红色线选定,对于接下了的标号为1,..,n的全部节点点,左右节点都只须要二选一便可获得不一样的生成树,这样的选择有 2^n种,太多

贪心算法的性质

  1. 最优子结构:有多个子结构的最优解最终组成整个问题的最优解
  2. 贪心算法的选择特定,会使得局部最优解最终也是全局最优解

寻找MST的最优子结构

假如边e={u,v}是某个MST的一条边,经过对合并这两个顶点为一个新的顶点(这种操做称做contract e),将有多条边同时链接多个顶点的合并成一个权重最小的边保留,其它边的链接形式保持不变。能够证实假设T'是G/e(不包含e的G)的MST,那么T'U{e}也是G的MST函数

证实

假设T*(e\in T^*)是G的MST,那么 T*/e(即T') 也是 G/e的MST,即spa

w(T')\leq w(T^*/e)

而w(T'Ue)=w(T')+w(e),因此.net

w(T'Ue) \leq w(T^*/e)+w(e)=w(T^*)

于是成立3d

MST的贪心选择

假设有任意的cut(S,V-S),选取e,使得e是全部crossing cut的最小权重的边(e={u,v},u\in S v\in V-S),那么e确定是属于某个MST。code

红色的线即 crossing cut的边cdn

证实

假设T是G的一个MST,那么它一定存在一条边e'={u',v'}横跨S和V/S,因为w(e)<=w(e'),能够构造T'=T/{e'}U{e}=w(T)-w(e')+w(e)<=w(T),也就是说T'也是MST,e属于某个MST。blog

Prim's算法

维护一个优先级队列Q,它的节点u.key=min{w(u,v)|u in s and v in (S-V)}

  • 随便选取单个节点做为S,其它的都是 S-V
  • 在Q中存储V全部的节点,对于节点s,有s.key=0,其它的是 无穷大
  • 只要Q中还有元素,获取最小的元素,遍历它的邻接表,若是节点v不在S里面,而且w(u,v)<v.key,更新v.key=w(u,v),记录v.parent=u

初始的图以下

选取节点s in S,其它的为V-S 按照初始化的规则获得

Q:{S.key=0,A.key=\infty,B.key=\infty,C.key=\infty,D.key=\infty,E.key=\infty,F.key=\infty,G.key=\infty}

而后获取最小key的节点,显然他就是S

获取S的全部邻接表,比较crossing cut的边的权值和当前Q中存储的key的大小,保留小的,获得

Q:{A.key=7,B.key=\infty,C.key=15,D.key=10,E.key=\infty,F.key=\infty,G.key=\infty}

再找到Q中最小的为A,将二者记下来

再查看全部S的邻接表,更新Q的权值,获得

Q:{B.key=9,C.key=15,D.key=10,E.key=\infty,F.key=5,G.key=12}

获取最小值为5,将它放入S中


再次更新Q获得

Q:{B.key=9,C.key=15,D.key=8,E.key=14,G.key=6}

获取最小是为6,获得

再更新Q

Q:{B.key=9,C.key=15,D.key=8,E.key=14}

最小值为8

更新Q获得

Q:{B.key=9,C.key=15,E.key=3}

最小值为3

更新Q获得

Q:{B.key=9,C.key=15}

最小值为9

更新Q获得

Q:{C.key=15}

最小值为15

最终获得MST为

运行时间

在整个过程当中,涉及V次的从优先级队列中获取最小值,以及边两倍次的减小key的值,因此总的时间为

O(V)T_{extractMin}+O(E)T_{decreaseKey}

使用斐波那契堆能够达到VlgV+E

Kruskal's算法

核心思想:全局最小的corssing cut边一定属于最小生成树,这个过程不能生成环,须要追踪两个节点是否已经互相链接了

追踪的数据结构是 Union-Find 结构,包含3个功能,Make-Set:建立一个集合;Find-Set:找到当前元素在那个集合;Union:合并集合

  • 刚开始的时候T什么都没有
  • 对每一个节点v都执行一遍Make-Set
  • 为了找到全局最小的crossing cut,对整个的边经过权值按照递增来排序
  • 按照增序遍历全部的边,若是两个节点u和v属于不一样的集合(crossing cut),那么能够合并边T=TU{e},而后将这两个集合合并Union(u,v)

延伸阅读 Union-Find数据结构Ackermann函数

时间分析

T_{sort}(E)+O(V)*T_{make-set}+O(E)(T_{Find}+T_{Union})

在使用Union-Find数据结构的基础上可以作到时间为O(ElgE+Eα(V)),假设权重为正整数并且最大值是个常量,那么排序能够达到常量的时间,这个时候,算法所须要的时间就是O(E),总体不Prims算法要好

最快的MST 算法运行指望时间是O(V+E),Karger, Klein, and Tarjan 1993发明

相关文章
相关标签/搜索