欢迎找我内推微软

[学习笔记]最小生成树

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代码待更新。

posted @ 2016-04-27 09:31  zmj97  阅读(229)  评论(0编辑  收藏  举报
欢迎找我内推微软