c++中如何实现克鲁斯卡尔算法_c++ Kruskal算法代码实现
发布时间 - 2026-01-04 00:00:00 点击率:次Kruskal易错因排序失效和并查集未优化:边须权重前置或自定义比较,UF必须路径压缩,验证需检查选边数是否为n-1且图连通。
为什么直接写 Kruskal 常常连边都排不对?
因为 std::sort 默认按第一个字段升序,而你传的边结构体或 std::tuple 如果没重载比较或写错 compare,排序就失效。常见错误是把权重放在结构体第二个字段却没自定义排序规则,结果算法从最大边开始选,根本得不到最小生成树。
推荐统一用 std::vector<:tuple int>> 存边:权重在前,sort 自然按权重升序;或者用结构体 + lambda:
std::vectoredges; std::sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b) { return a.weight < b.weight; });
并查集(Union-Find)不路径压缩会超时吗?
会。尤其点数 > 1e4 时,朴素 find 可能退化成 O(n) 单次查询,整体复杂度接近 O(mn),Kruskal 就失去意义。必须做路径压缩 + 按秩合并(或只做路径压缩也够大多数 OJ 场景)。
关键实现要点:
-
parent[i] = i初始化不能漏 -
find中递归调用后要赋值更新:return parent[x] = find(parent[x]) -
unionSet里判断的是rootA != rootB,不是a != b
struct UnionFind {
std::vector parent, rank;
UnionFind(int n) : parent(n), rank(n, 0) {
for (int i = 0; i < n; ++i) parent[i] = i;
}
int find(int x) {
return parent[x] == x ? x : parent[x] = find(parent[x]);
}
bool unionSet(int a, int b) {
int ra = find(a), rb = find(b);
if (ra == rb) return false;
if (rank[ra] < rank[rb]) std::swap(ra, rb);
parent[rb] = ra;
if (rank[ra] == rank[rb]) rank[ra]++;
return true;
}
}; 输入边时顶点编号从 0 还是 1 开始?
取决于题干。国内 OJ(如洛谷、PTA)多数用 1-indexed 顶点,但 UnionFind 类内部下标是 0-based,所以读入后立刻减 1,别等到排序或合并时再处理——容易忘、易出界、调试困难。
例如输入 u v w,统一转成:
int u, v, w; std::cin >> u >> v >> w; edges.emplace_back(w, u - 1, v - 1); // 权重前置,顶点归零
后续所有 unionSet(u-1, v-1)、find(u 都基于 0-indexed,逻辑干净。
-1)
如何验证 Kruskal 输出的边确实构成 MST?
最简验证方式:检查是否恰好选了 n - 1 条边,且总权重与标准答案一致。更稳妥的做法是,在每次 unionSet 成功后记录该边,并确保最终 result.size() == n - 1;若提前结束(边用完但没凑够),说明图不连通——这时应返回错误或输出 -1,而不是强行输出部分结果。
典型收尾逻辑:
int cnt = 0, totalWeight = 0;
for (auto [w, u, v] : edges) {
if (uf.unionSet(u, v)) {
totalWeight += w;
cnt++;
if (cnt == n - 1) break;
}
}
if (cnt != n - 1) {
std::cout << "-1\n"; // 不连通
} else {
std::cout << totalWeight << "\n";
}注意:不要在循环外再查 uf.find(0) == uf.find(i) 判断连通性——Kruskal 过程中已隐含该信息,重复检查无必要且易错。
真正容易被忽略的是:当存在多条相同权重的边时,sort 的稳定性不影响正确性,但不同实现可能选出不同的 MST(只要总权相等就合法)。如果题目要求输出字典序最小的边集,就得在权重相同时按端点二次排序——这点几乎没人提,但现场笔试真会卡。
# edge
# c++
# 为什么
# sort
# 结构体
# union
# 递归
# 循环
# Lambda
# 算法
# 的是
# 升序
# 自定义
# 放在
# 第一个
# 没人
# 第二个
# 就得
# 而你
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
网页设计与网站制作内容,怎样注册网站?
zabbix利用python脚本发送报警邮件的方法
如何在企业微信快速生成手机电脑官网?
JS去除重复并统计数量的实现方法
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
Laravel项目怎么部署到Linux_Laravel Nginx配置详解
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
JavaScript如何实现倒计时_时间函数如何精确控制
Swift开发中switch语句值绑定模式
今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】
太平洋网站制作公司,网络用语太平洋是什么意思?
如何确保西部建站助手FTP传输的安全性?
Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】
如何在景安云服务器上绑定域名并配置虚拟主机?
如何在局域网内绑定自建网站域名?
如何在云指建站中生成FTP站点?
Python自动化办公教程_ExcelWordPDF批量处理案例
linux写shell需要注意的问题(必看)
微信h5制作网站有哪些,免费微信H5页面制作工具?
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
javascript中的try catch异常捕获机制用法分析
昵图网官方站入口 昵图网素材图库官网入口
Laravel如何升级到最新版本?(升级指南和步骤)
EditPlus 正则表达式 实战(3)
千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】
JavaScript常见的五种数组去重的方式
如何快速搭建二级域名独立网站?
Laravel怎么实现微信登录_Laravel Socialite第三方登录集成
微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】
Laravel如何创建自定义Artisan命令?(代码示例)
高端企业智能建站程序:SEO优化与响应式模板定制开发
大学网站设计制作软件有哪些,如何将网站制作成自己app?
微信小程序 HTTPS报错整理常见问题及解决方案
网站建设要注意的标准 促进网站用户好感度!
Laravel如何实现事件和监听器?(Event & Listener实战)
百度输入法ai组件怎么删除 百度输入法ai组件移除工具
Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)
如何在宝塔面板中创建新站点?
如何在建站之星网店版论坛获取技术支持?
如何基于PHP生成高效IDC网络公司建站源码?
免费视频制作网站,更新又快又好的免费电影网站?
轻松掌握MySQL函数中的last_insert_id()
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
如何在Windows服务器上快速搭建网站?
图册素材网站设计制作软件,图册的导出方式有几种?
HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】
MySQL查询结果复制到新表的方法(更新、插入)
高端智能建站公司优选:品牌定制与SEO优化一站式服务
javascript基于原型链的继承及call和apply函数用法分析

