zoukankan      html  css  js  c++  java
  • [学习笔记]最小生成树

    Minimum Spanning Tree

    生成树
      如果连通图G的一个子图是一棵包含G的所有顶点的树,则该子图称为G的生成树(Spanning Tree)。
           图的生成树不惟一。
    最小生成树

      生成树T各边的权值总和称为该树的权;权最小的生成树称为G的最小生成树(Minimum SpannirngTree)。最小生成树可简记为MST

    MST性质:

      假设N=(V,{E})是一个连通网,U是顶点集V的一个非空子集。若(u,v)是一条具有最小权值(代价)的边,其中u∈U,v ∈V-U,则最小生成树中必包含边(u,v)

      证明(反证法):(u,v)是一条具有最小权值(代价)的边,如果最小生成树不包含它,势必要包含其他边,以使U和V-U两个集合连通。无论是包含其他边中的哪一条,其权值都会比(u,v)更大,导致总的权值之和也更大。

    算法:

      算法一:

        Prim算法(普里姆算法)

        基本思想:取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w。在添加的顶点 w 和已经在生成树上的顶点v 之间必定存在一条边,并且该边的权值在所有连通顶点 v 和 w 之间的边中取值最小。之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止。

        适用于稠密图

      算法二:

        Kruskal算法(克鲁斯卡尔算法)

        基本思想:考虑问题的出发点: 为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能地小。具体做法: 先构造一个只含 n 个顶点的子图 SG,然后从权值最小的边开始,若它的添加不使SG 中产生回路,则在 SG 上加上这条边,如此重复,直至加上 n-1 条边为止。

        适用于稀疏图

    以下是代码:

     1 void Prim(int n, int **weight)
     2 {
     3     int lowest_weight[n+1];
     4     int closest_vertex[n+1];
     5     bool has_been_added[n+1];
     6     has_been_added[1] = true;
     7     for (int i = 2; i <= n; i++)                // 初始化
     8     {
     9         lowest_weight[i] = weight[1][i];
    10         closest_vertex[i] = 1;
    11         has_been_added[i] = false;
    12     }
    13     for (int i = 1; i < n; i++)
    14     {
    15         int lowest_weight_of_all_edges = inf;    // 把当前最小权定义为无限大
    16         int vertex_will_be_added = 1;
    17         for (int j = 2; j <= n; j++)            // 找出本次添加的点
    18         {
    19             if ((!has_been_added[j])&&(lowest_weight[j]<lowest_weight_of_all_edges))
    20             {
    21                 lowest_weight_of_all_edges = lowest_weight[j];
    22                 vertex_will_be_added = j;
    23             }
    24         }
    25         has_been_added[j] = true;
    26         cout<<"this time we add : "<<vertex_will_be_added<<" by "<<closest_vertex[vertex_will_be_added]<<endl;
    27         for (int j = 2; j <=n ; j++)            // 更新最小权
    28         {
    29             if ((!has_been_added[j])&&(weight[vertex_will_be_added][j]<lowest_weight[j]))
    30             {
    31                 lowest_weight[j] = weight[vertex_will_be_added][j];
    32                 closest_vertex[j] = vertex_will_be_added;
    33             }
    34         }
    35     }
    36 }

     kruskal代码待更新。

  • 相关阅读:
    .NET 2.0 WinForm Control DataGridView 编程36计(一)
    Sql Server 日期格式化函数
    FastReport 金额大小写转换自定义函数
    vue.js 三种方式安装(vuecli)
    Android style
    android ui 布局性能优化
    android 手机分辨率
    TCP,IP,HTTP,SOCKET区别和联系
    android2.2 特性
    常见开放api平台OpenAPI
  • 原文地址:https://www.cnblogs.com/zmj97/p/5436758.html
Copyright © 2011-2022 走看看