zoukankan      html  css  js  c++  java
  • 最小生成树-Prim算法

    一、基本概念

    1.连通图:在无向图中,若任意两个顶点都有路径相通,则称该无向图为连通图。

    2.连通网:在连通图中,若图的边具有一定的意义,每一条边都对应着一个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通网。

    3.生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。

    4.最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。 

    二、prim算法

    • 基本思想: 

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

     一般情况下所添加的顶点应满足下列条件:

    在生成树的构造过程中,图中 n 个顶点分属两个集合:已落在生成树上的顶点集 U 和尚未落在生成树上的顶点集V-U ,则应在所有连通U中顶点和V-U中顶点的边中选取权值最小的边。

    需要设一个辅助数组:

    struct node{
      VertexData AdjVertex;
      int lowestcost;
    }closedge[105];     

    用下标表示未在生成树上的点,AdjVertex存储在生成树上的点,两点连成一个边,lowestcost表示权值,。最后得到的数组中存储的就是最小生成树的边。

    • 过程图示:

     

    •  代码:
      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 #define VertexData int
      6 #define INFINITE 1000000007
      7 
      8 typedef struct{
      9     int AdjMatrix[105][105]; // 邻接矩阵
     10     int vertex_num; // 点的个数
     11     //int arc_num;
     12     //VertexData vertex[105];
     13 }Graph;
     14 
     15 struct node{
     16     VertexData AdjVertex; // 生成树中的点
     17     int lowestcost; // 权值
     18 }closedge[105];
     19 char vextex[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
     20 
     21 // 初始化邻接矩阵
     22 void Build_Matrix(Graph *G) {
     23     for (int i = 0; i < G->vertex_num; i++)
     24         for (int j = 0; j < G->vertex_num; j++) {
     25             G->AdjMatrix[i][j] = INFINITE;
     26             G->AdjMatrix[j][i] = INFINITE;
     27         }
     28 }
     29 
     30 // 返回最小权值的边
     31 int getmin(int n) {
     32     int Min = INFINITE;
     33     int index = -1;
     34     for(int i = 0; i < n; i++) {
     35         if(closedge[i].lowestcost && closedge[i].lowestcost < Min) {
     36             Min = closedge[i].lowestcost;
     37             index = i;
     38         }
     39     }
     40     return index;
     41 }
     42 
     43 // prim算法
     44 void prim(Graph G, VertexData s) {
     45     // 初始化辅助数组
     46     for (int i = 0; i < G.vertex_num; i++) {
     47         closedge[i].lowestcost = INFINITE;
     48     }
     49     // 先存入起始点
     50     closedge[s].AdjVertex = s;
     51     closedge[s].lowestcost = 0;
     52     for(int i = 0; i < G.vertex_num; i++) {
     53         if(i != s) {
     54             closedge[i].AdjVertex = s;
     55             closedge[i].lowestcost = G.AdjMatrix[s][i];
     56         }
     57     }
     58     // 最多循环顶点个数n-1次
     59     for(int i = 0; i < G.vertex_num-1; i++) {
     60         int k = getmin(G.vertex_num);
     61         if(k == -1) break;
     62         cout << vextex[closedge[k].AdjVertex] << "--" << vextex[k] << endl;
     63         closedge[k].lowestcost = 0; // 权值赋0表示将该点并入最小生成树的集合
     64         // 更新树外最小代价边的信息
     65         for(int j = 0; j < G.vertex_num; j++) {
     66             if(G.AdjMatrix[k][j] < closedge[j].lowestcost) {
     67                 closedge[j].lowestcost = G.AdjMatrix[k][j];
     68                 closedge[j].AdjVertex = k;
     69             }
     70         }
     71     }
     72 }
     73 
     74 int main() {
     75     int m, n, a, b;
     76     Graph G;
     77 
     78     int ans = 0, cost, counter = 0;
     79     cout << "输入点个数" << endl;
     80     cin >> m;
     81     G.vertex_num = m;
     82     Build_Matrix(&G);
     83     cout << "输入边个数" << endl;
     84     cin >> n;
     85     cout << "输入边信息" << endl;
     86     for (int i = 0; i < n; i++) {
     87         cin >> a >> b >> cost;
     88         G.AdjMatrix[a][b] = cost;
     89         G.AdjMatrix[b][a] = cost;
     90     }
     91     prim(G, 0);
     92     return 0;
     93 }
     94 
     95 
     96 /*
     97  *
     98 
     99 6
    100 10
    101 0 1 6
    102 0 2 1
    103 0 3 5
    104 1 2 5
    105 1 4 3
    106 2 3 5
    107 2 4 6
    108 2 5 4
    109 3 5 2
    110 4 5 6
    111  * */
    112 /*
    113     int locate(Graph G, char c) {
    114         for(int i = 0; i < G.vertex_num; i++) {
    115             if(G.vertex[i] == c)
    116                 return i;
    117         }
    118         return -1;
    119     }
    120 */

    三、例题

    通畅工程:

    Description

    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。 
     

    Input

    测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N 
    行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。 
     

    Output

    对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。 
     

    Sample Input

    3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100
     

    Sample Output

    3 ?

     ac代码:

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define VertexData int
     6 #define INFINITE 10000000007
     7 
     8 typedef struct{
     9     //VertexData vertex[1005];
    10     int AdjMatrix[105][105];
    11     //int arc_num;
    12     int vertex_num;
    13 }Graph;
    14 
    15 struct node{
    16     VertexData AdjVertex;
    17     int lowestcost;
    18 }closedge[105];
    19 
    20 
    21 void Build_Matrix(Graph *G) {
    22     for (int i = 0; i < G->vertex_num; i++)
    23         for (int j = 0; j < G->vertex_num; j++) {
    24             G->AdjMatrix[i][j] = INFINITE;
    25             G->AdjMatrix[j][i] = INFINITE;
    26         }
    27 }
    28 
    29 int getmin(struct node *closedge, int n) {
    30     int Min = INFINITE;
    31     int index = -1;
    32     for(int i = 0; i < n; i++) {
    33         if(closedge[i].lowestcost && closedge[i].lowestcost < Min) {
    34             Min = closedge[i].lowestcost;
    35             index = i;
    36         }
    37     }
    38     return index;
    39 }
    40 
    41 void prim(Graph G, VertexData s) {
    42     for (int i = 0; i < G.vertex_num; i++) {
    43         closedge[i].lowestcost = INFINITE;
    44     }
    45     closedge[s].AdjVertex = s;
    46     closedge[s].lowestcost = 0;
    47     for(int i = 0; i < G.vertex_num; i++) {
    48         if(i != s) {
    49             closedge[i].AdjVertex = s;
    50             closedge[i].lowestcost = G.AdjMatrix[s][i];
    51         }
    52     }
    53     for(int i = 0; i < G.vertex_num-1; i++) {
    54         int k = getmin(closedge, G.vertex_num);
    55         if(k == -1) break;
    56         closedge[k].lowestcost = 0;
    57         for(int j = 0; j < G.vertex_num; j++) {
    58             if(G.AdjMatrix[k][j] < closedge[j].lowestcost) {
    59                 closedge[j].lowestcost = G.AdjMatrix[k][j];
    60                 closedge[j].AdjVertex = k;
    61             }
    62         }
    63     }
    64 }
    65 
    66 int main() {
    67     int m, n, a, b;
    68     Graph G;
    69     while(~scanf("%d%d", &n, &m)) {
    70         if(!n) break;
    71         int ans = 0, cost, counter = 0;
    72         G.vertex_num = m;
    73         Build_Matrix(&G);
    74         for (int i = 0; i < n; i++) {
    75             cin >> a >> b >> cost;
    76             G.AdjMatrix[a-1][b-1] = cost;
    77             G.AdjMatrix[b-1][a-1] = cost;
    78         }
    79 
    80         prim(G, 0);
    81         for(int i = 1; i < m; i++) {
    82             if(closedge[i].lowestcost == 0) {
    83                 ans += G.AdjMatrix[i][closedge[i].AdjVertex];
    84                 counter++;
    85             }
    86         }
    87         if(counter != m-1)
    88             cout << "?" << endl;
    89         else
    90             cout << ans << endl;
    91     }
    92     return 0;
    93 }

    参考博客:https://blog.csdn.net/a2392008643/article/details/81781766

  • 相关阅读:
    Jmeter之参数化
    安全测试-业务安全的些许“瞎说”
    (转)LR性能测试结果样例分析
    (转)使用 Nmon 监控 Linux 的系统性能
    Jmeter之断言
    自动化框架httpClient实例
    RabbitMQ集群 Docker一键部署
    使用swing构建一个界面(包含flow ,Border,Grid,card ,scroll布局)
    Jtable实现
    java 使用最新api操作mongodb
  • 原文地址:https://www.cnblogs.com/knightoflake/p/13932918.html
Copyright © 2011-2022 走看看