最小生成树(贪心算法)

最小生成树问题——连接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,初始化的时候就需要构造最小优先队列;而更新之后也得保持最小优先队列的性质

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

G11176593

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值