最小生成树
最小生成树
最小生成树的算法有两种
我们一般遇到稠密图都会用到朴素版Prim,稀疏图都会用Kruskal
因为这样代码最短
朴素版Prim算法
Prim根dijkstra长得特别像
算法实现:
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 510, INF = 0x3f3f3f3f; int n, m; int g[N][N]; int dist[N]; bool st[N]; int prim() { memset(dist, 0x3f, sizeof dist); int res = 0; for (int i = 0; i < n; i ++ ) { int t = -1; for (int j = 1; j <= n; j ++ ) if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j; // 如果没有找到最小点,那么直接return INF if (i && dist[t] == INF) return INF; // 先加上边权,防止有自环是负的情况 if (i) res += dist[t]; for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]); st[t] = true; } return res; } int main() { scanf("%d%d", &n, &m); memset(g, 0x3f, sizeof g); while (m -- ) { int a, b, c; scanf("%d%d%d", &a, &b, &c); g[a][b] = g[b][a] = min(g[a][b], c); } int t = prim(); if (t == INF) printf("impossible\n"); else printf("%d\n", t); return 0; }
堆优化版Prim就是将dist数组简称堆,查询最小值就是O(1)的,插入是logn的
Kruskal算法
这个第二步可以用并查集来优化
算法实现:
#include <iostream> #include <algorithm> using namespace std; const int N = 200010; int n, m; int p[N]; struct Edge { int a, b, w; bool operator< (const Edge &W)const { return w < W.w; } }edges[N]; int find(int x) { if (p[x] != x) return find(p[x]); return p[x]; } int main() { scanf("%d%d", &n, &m); for (int i = 0; i < m; i ++ ) { int a, b, c; scanf("%d%d%d", &a, &b, &c); edges[i].a = a, edges[i].b = b, edges[i].w = c; } for (int i = 1; i <= n; i ++ ) p[i] = i; sort(edges, edges + m); int res = 0, cnt = 0; for (int i = 0; i < m; i ++ ) { int a = edges[i].a, b = edges[i].b, w = edges[i].w; a = find(a), b = find(b); if (a != b) { p[a] = b; res += w; cnt ++ ; } } if (cnt < n - 1) printf("impossible\n"); else printf("%d\n", res); return 0; }
本文作者:张詠然
本文链接:https://www.cnblogs.com/zyrddd/p/16637539.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步