最小生成树算法

Posted dynastysun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小生成树算法相关的知识,希望对你有一定的参考价值。

最小生成树有两种算法:Kruskal算法 和 Prim算法

算法一:Kruskal算法

基本思想就是:每次选择目前剩余的边中的权值最小的边,若将此边加入图中,不会形成环,则可以加入图中,否则舍弃。判断是否会形成环可以使用并查集算法。

以 HDU - 1879 题为例(题目链接:https://vjudge.net/problem/HDU-1879 ),代码如下:

技术分享图片
 1 #include <algorithm>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <iostream>
 5 #include <cstring>
 6 #include <map>
 7 #include <cmath>
 8 using namespace std;
 9 
10 const int maxn = 100 + 10;
11 int N, M;
12 
13 int ans, f[maxn];
14 
15 struct Node{
16     int x, y, d;
17     Node(int x=0,int y=0,int d=0):x(x),y(y),d(d){}
18     bool operator < (const Node& t) const {
19         return d < t.d;
20     }
21 };
22 Node edge[maxn*maxn];
23 
24 // 并查集
25 int find(int a) {
26     return f[a] == a ? a : f[a]=find(f[a]);
27 }
28 
29 void Kruskal(){
30     for(int i = 1; i <= N; ++i) f[i] = i;
31 
32     //按照边的权值从小到大进行选取
33     for(int i = 0; i < M; ++i){
34         int u = find(edge[i].x);
35         int v = find(edge[i].y);
36         if(u != v){
37             f[u] = v;
38             ans += edge[i].d;
39         }
40     }
41 }
42 
43 int main(){
44     while(scanf("%d", &N) == 1 && N){
45         M = N*(N-1)/2;
46         for(int i = 0; i < M; ++i){
47             int u, v;
48             scanf("%d%d%d%d", &edge[i].x, &edge[i].y, &u, &v);
49             if(v == 1) edge[i].d = 0;
50             else edge[i].d = u;
51         }
52         sort(edge, edge+M);
53         ans = 0;
54         Kruskal();
55         cout << ans << endl;
56     }
57     return 0;
58 }
View Code

这个算法是按照边来计算的,所以算法复杂度为O(eloge),下面的Prim算法是依据结点来计算的,复杂度是O(n^2)

算法二:Prim算法

基本思想和Dijkstra算法思想有点类似,可以参考Dijkstra算法的思想,链接:https://www.cnblogs.com/DynastySun/p/9351584.html,代码如下:

技术分享图片
 1 #include <algorithm>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <iostream>
 5 #include <cstring>
 6 #include <map>
 7 #include <cmath>
 8 using namespace std;
 9 
10 const int INF = 0x3f3f3f3f;
11 const int maxn = 100 + 10;
12 
13 int ans, N, M, G[maxn][maxn];
14 
15 void Prim(){
16     int start = 1;
17     int flag[maxn], dis[maxn];
18     memset(flag, 0, sizeof(flag));
19     for(int i = 1; i <= N; ++i) {
20         dis[i] = G[i][1];
21         last[i] = start;
22     }
23     dis[start] = 0;
24     flag[start] = 1;
25     for(int i = 1; i < N; ++i){
26         int MIN = INF;
27         int k;
28         for(int j = 1; j <= N; ++j)
29             if(!flag[j] && MIN > dis[j]){
30                 MIN = dis[j];
31                 k = j;
32             }
33 
34         flag[k] = 1;
35         ans += MIN;
36 
37         for(int j = 1; j <= N; ++j)
38             if(!flag[j] && dis[j] > G[j][k]) {
39                 dis[j] = G[k][j];
40             }
41     }
42 }
43 
44 int main(){
45     while(scanf("%d", &N) == 1 && N){
46         memset(G, INF, sizeof(G));
47         M = N*(N-1)/2;
48         for(int i = 0; i < M; ++i){
49             int a, b, c, d;
50             scanf("%d%d%d%d", &a, &b, &c, &d);
51             if(d == 1) G[a][b] = G[b][a] = 0;
52             else G[a][b] = G[b][a] = c;
53         }
54         ans = 0;
55         Prim();
56         printf("%d
", ans);
57     }
58     return 0;
59 }
View Code

 

以上是关于最小生成树算法的主要内容,如果未能解决你的问题,请参考以下文章

最小生成树详解 prim+ kruskal代码模板

最小生成树及Prim算法及Kruskal算法的代码实现

图的最小生成树算法(图解+代码)| 学不会来看我系列

最小生成树

最小生成树算法:Kruskal算法 Prim算法

急!数据结构最小生成树prim算法C语言实现