14.Prim算法求最小生成树

 

 最小生成树的图对应的图都是无向图,最小生成树没有自环

稠密图用朴素版的Prim算法,O(n ^ 2)

稀疏图用堆优化版的Prim算法,O(m log n)

Kruskal算法,O(m log m)和O(m log n)级别一样,m < n ^ 2,先对所有边从小到大排序

如何选择:

稠密图直接朴素版的Prim算法

稀疏图Kruskal算法

堆优化版的Prim算法一般不常用

二分图:

 如何判断一个图是不是二分图:dfs,染色法,O(n + m)

匈牙利算法:求二分图的最大匹配,最坏O(nm),一般远小于

 先讲朴素版的Prim算法

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 510, INF = 0x3f3f3f3f;
 4 int g[N][N]; //邻接矩阵
 5 int dist[N];
 6 bool st[N];
 7 int n, m;
 8 int prim() {
 9     memset(dist, 0x3f, sizeof dist); //初始化距离
10     int res = 0; //最小生成树里所有边的长度之和
11     for (int i = 0; i < n; i++) { //n次迭代
12         int t = -1;
13         for (int j = 1; j <= n; j++) {
14             if (!st[j] && (t == -1 || dist[t] > dist[j])) {
15                 t = j;
16             }
17             //t == -1表示如果还没有找到一个点
18         } //找到不在集合当中的,距离最近的点
19         //集合的意思是:当前的生成树,当前的这个连通块
20         //集合S表示,当前已经在连通块中的所有的点
21         if (i && dist[t] == INF) { //如果不是第一个点的话
22             return INF; //不连通的话,不存在最小生成树
23         }
24         if (i) { //只要不是第一个点
25             res += dist[t];
26         } //先加进去再更新
27         for (int j = 1; j <= n; j++) { //更新距离
28             dist[j] = min(dist[j], g[t][j]); //这个点到集合的距离
29         }
30         st[t] = true;
31     }
32     return res;
33 }
34 int main() {
35     cin >> n >> m;
36     memset(g, 0x3f, sizeof g);
37     while (m--) {
38         int a, b, c;
39         cin >> a >> b >> c;
40         g[a][b] = g[b][a] = min(g[a][b], c); //重边只留最小边
41     }
42     int t = prim();
43     if (t == INF) {
44         cout << "impossible" << endl;
45     } else {
46         cout << t << endl;
47     }
48     return 0;
49 }

 

posted @ 2020-07-25 02:51  kyk333  阅读(348)  评论(0)    收藏  举报