Kruskal算法求最小生成树
c++
Kruskal算法求最小生成树
/* * 最小生成树 * 最小生成树是图论中最为常见的问题之一,不过相比于最短路中的单源最短路和多源最短路,最小生成树算法主流仅有两种。 * 分别是 Prim 算法和 Kruskal 算法。这两个算法一个是基于点的算法,一个是基于边的算法。 * 这两者的关系有些像 最短路中 Dijkstra 和 Bellmanford。其中,Prim 算法和 Dijkstra 的流程图几乎一致。 * 此次,我们将要介绍著名的 Kruskal 算法。 * * 算法流程: * Step 1: * 将所有的边按照边权大小从小到大排序。 * Step 2: * 按照从小到大的顺序遍历所有的边,对每一个边 edge 的端点 u, v,倘若 u v 不在一个连通域内,那么就将 u v相连。 * Step 3: * 倘若最后,所有的点都进入了同一个连通域,那么最小生成树构成。否则,最小生成树不存在。 * 算法证明: * 对于这种迭代算法,仅需要证明其在 for 循环中,算法仍然成立即可。 * 假如说,我们边为 edge1 时候,u v 端点不在同一个连通域中,不妨考虑,有没有一种可能,不加入 edge1 使得 u v相连通了呢? * * 假如说,有一种解决方案,得到了最小生成树,并没有用到 edge1。但是从我们排序边这个做法可以知道,edge1 绝对是 连接 u, v代价最小的办法。 * 因此将 edge1 放到这个最小生成树中,必定可以找到环中 大于等于 edge1 权重的边,将其拿下,还是最小生成树。 * 不断迭代,可以说明,我们这样是对的。 * * 算法复杂度: * 算法主要复杂度是对边的排序,算法复杂度为 M log M * 注意点: * 这是无向图,排序和并查集 */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <vector> #include <queue> using namespace std; const int N = 100010, M = 200010, INF = 0x3f3f3f3f; class Edge { public: int u, v, w; }; Edge e[M]; int n, m; int fa[N]; bool cmp(Edge t1, Edge t2) { return t1.w < t2.w; } int Find(int x) { if (fa[x] == x) { return x; } else { return fa[x] = Find(fa[x]); } } void Union(int x, int y) { x = Find(x), y = Find(y); fa[x] = y; } int main() { scanf("%d%d", &n, &m); for (int i = 1, a, b, c; i <= m; i ++ ) { scanf("%d%d%d", &a, &b, &c); e[i].u = a, e[i].v = b, e[i].w = c; } sort(e + 1, e + m + 1, cmp); for (int i = 1; i <= n; i ++ ) { fa[i] = i; } int ret = 0, cnt = 0; for (int i = 1; i <= m; i ++ ) { if (Find(e[i].u) == Find(e[i].v)) { continue; } else { Union(e[i].u, e[i].v); ret += e[i].w; cnt += 1; } } if (cnt == n - 1) { printf("%d\n", ret); } else { printf("impossible\n"); }; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)