最小生成树(贪心算法)

最小生成树问题——连接n个针脚,可以使用n-1根连线,每个连线连接两个针脚,使得所使用的连线长度最短
    抽象为图问题,一个连通无向图G = (V, E),V是针脚的集合,E是针脚之间的可能连接,且对于每条边都有权重w(u, v),希望找到一个无环子集,T属于E,权重之和最小

通用方法——在每个时刻生长最小生成树的一条边,并在整个策略的实施过程中,管理一个遵守下述循环不变式的边集合A:
    每遍循环之前,A是某棵最小生成树的一个子集
    即在每一步,选择一条边(u, v),将其加入到集合A中【贪心算法】,使得A不违反循环不变式;这样的边成为集合A的 安全边
GENERIC-MST(G, w)
    A = 空集
    while A does not form a spanning tree            //A还不是生成树
        find an edge(u, v) that is safe for A
        A = A 并上 {(u, v)}
    return A

    Kruskal算法和Prim算法在确定安全边的细节有所不同
     在Kruskal算法中,集合A是一个森林,其结点就是给定图中的结点,每次加入到集合A中的安全变永远是权重最小的链接两个不同分量的边; Prim算法里,集合A是一棵树,每次加入到A中的安全变永远是连接A和A之外某个结点的边中权重最小的边。

Kruskal算法——在所有连接森林中两棵不同树的边里面,找到权重最小的边(u, v)
    使用不想交集合结构来维护几棵互不相交的树,即元素集合;FIND-SET(u)能够找到u所在的集合的代表,因此判断两个元素是否在同一个集合,只需要FIND-SET(u) == FIND-SET(v)
MST-KRUSKAL(G, w)
    A = 空集
    for each vertex v 属于 G.V
        MAKE-SET(v)
    sort the edegs of G.E into nondecreasing order by weight w
    for each edge(u, v)属于G.E, taken in nondecreasing order by weight
        if FIND-SET(u) != FIND-SET(v)
            A = A 并上 {(u, v)}
            UNION(u, v)                //将两棵树合并
    return A

Prim算法——在连接集合A和A之外的结点的所有边中,选择一条轻量级边加入到A中
    所有不在树A中的结点都存放在一个基于key属性的 最小优先队列Q中;对于每个结点v,属性v.key保存的是连接v和树中结点的所有边中最小边的权重(如果不存在则为INF);v.p给出结点v在树中的父结点
    从结点r出发构造,集合A维持在A = {(v, v.p) : v 属于 V - {r} - Q};最后生成的最小生成树为A = {(v, v.p) : v 属于 V - {r}}
MST-PRIM(G, w, r)
    for each u 属于 G.V
        u.key = INF
        u.p = NIL
    r.key = 0
    Q = G.V
    while Q != 空                                 //即还有结点没包含在生成树中
        u = EXTRACT-MIN(Q)               //提取权重最小的安全边
        for each v 属于 G.Adj[u]
            if v 属于Q and w(u, v)< v.key         //还在Q中(即还没选择进来)的需要更新
                v.p = u
                v.key = w(u, v)
     上面的过程少了构造最小优先队列一步,比如初始结点为r,则Q中存储的u.key不应该都为INF,初始化的时候就需要构造最小优先队列;而更新之后也得保持最小优先队列的性质
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值