14. 图--最小生成树

来源:互联网 发布:保障网络和信息安全 编辑:程序博客网 时间:2024/06/06 06:40

最小生成树

Minimum Spanning Tree

定义

  • 是一棵树
    • 无回路
    • V个顶点一定有V1条边
  • 是生成树
    • 包含全部顶点
    • V1条边都在图里
  • 边的权重和最小

注:

  • 向生成树中任加一条边都一定构成回路
  • 最小生成树存在 图连通

生成算法

最小生成树算法是贪心算法的应用。

  • 什么是“贪”:每一步都要最好的
  • 什么是“好”:权重最小的边
  • 需要约束:
    • 只能用图里有的边
    • 只能正好用掉V1条边
    • 不能有回路

Prim算法

算法:让一棵小树长大,适用于稠密图

实现

  • MST:最小生成树的集合,记录收录的顶点
  • dist[]:未收录顶点到最小生成树的最小距离(值为到某个顶点的最小距离)
    • 初始化为E<s,v>的值,如果与源点s没有直接的边相连,则初始化为正无穷
  • parent[]:记录生成树的每个结点的父结点,初始化为-1(或者仅初始化源点s
void Prim() {    MST = {s};    while (true) {        V = 未收录顶点中dist最小者;        if ( 这样的V不存在 )            break;        将V收录进MST:dist[V] = 0;        for ( V 的每个邻接点 W ) {            if (dist[w] != 0 && E<V, W> < dist[W]) {                dist[W] = E<V, W>;                parent[W] = V;            }        }    }    if ( MST中收录的顶点未包含全部顶点 )        Error( "生成树不存在" );}

如果采用邻接矩阵进行存储,同时通过扫描的方式取得未收录顶点中dist最小者,则时间复杂度为T=O(V2)

Kruskal算法

算法:把每个顶点视为一棵树,通过添加边把树合并成更大的树,更适用于稀疏图

实现

  • MST:记录最小生成树添加入的边
  • E:边集合
void Kruskal(Graph G) {    MST = { };    while ( MST中不到 V - 1 条边 && E 中还有边 ) {        从 E 中取一条权重最小的边 E<V, W>;  // 使用最小堆实现        将 E<V, W>从 E 中删除;        if ( E<V, W> 不在 MST 中构成回路 ) { // 使用并查集实现,如果V、W两个结点不在同一个集合中,则说明不构成回路            将 E<V, W> 加入 MST;        } else             彻底无视 E<V, W>;    }    if ( MST中不到 V - 1 条边 )         Error( "生成树不存在" );}

采用邻接表实现,时间复杂度为T=O(ElogE)

原创粉丝点击