算法学习笔记(30)——Kruskal算法(最小生成树)
Kruskal 算法
首先,将所有边按照权重从小到大排序。这一步是Kruskal算法的性能瓶颈,时间复杂度为 。不过由于排序的时间复杂度常数很小,所以Kruskal算法实际上是很快的。
第二部从小到大枚举每条边 ,边权为 ,如果 和 目前不在一个连通块中,就把这条边加入最小生成树。该部分可以用并查集来实现。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10, M = 2e5 + 10;
struct Edge
{
int a, b, w;
// 运算符重载(常量成员函数)
bool operator< (const Edge &e) const {
return w < e.w;
}
}edges[M];
int n, m;
int p[N]; // 并查集
// 并查集查找操作(路径压缩优化)
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void kruskal()
{
// 首先对所有边按边权从小到大排序
sort(edges, edges + m);
// 初始化并查集
for (int i = 1; i <= n; i ++ ) p[i] = i;
// res存储最小生成树的边权之和,cnt存储最小生成树的边数
int res = 0, cnt = 0;
// 从小到大枚举每条边
for (int i = 0; i < m; i ++ ) {
auto e = edges[i];
int a = e.a, b = e.b, w = e.w;
// 如果a和b不在同一集合,则将这条边加入最小生成树
if (find(a) != find(b)) {
p[find(a)] = find(b);
res += w;
cnt ++;
}
}
// 根据最小生成树定义判断(n个点的最小生成树的边数一定为n-1)
if (cnt < n - 1) puts("impossible");
else cout << res << endl;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i ++ ) {
int u, v, w;
cin >> u >> v >> w;
edges[i] = {u, v, w};
}
kruskal();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通