最小生成树-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

原文地址:https://www.cnblogs.com/knightoflake/p/13932918.html