C++实现克鲁斯卡尔算法 _ 最小生成树与边集排序【源码】

老敏小哥_3999

老敏小哥_3999

2026-04-13

532人浏览

原创

克鲁斯卡尔算法需边排序+并查集判环:用std::sort按权值(及次级键)升序排序边,配合路径压缩+按秩合并的并查集检测环;边数不足v-1时图不连通,应返回空。

c++实现克鲁斯卡尔算法 _ 最小生成树与边集排序【源码】

克鲁斯卡尔算法的核心是边排序 + 并查集判环

直接说结论:不用自己手写快排,std::sort 配合自定义比较函数就足够;但必须用并查集(Disjoint Set Union)判断加入某条边是否成环,否则时间复杂度退化到 O(E²)。常见错误是把“按权值排序”当成全部逻辑,漏掉环检测——结果生成的不是树,而是带环图或森林。

典型使用场景:稀疏图(E ≈ V)、边已显式给出(如输入就是边列表)、需要输出最小生成树的边集而非仅权值和。

  • std::vector<:tuple int>></:tuple> 存边:(weight, u, v),方便用 std::sort 默认升序
  • 并查集必须路径压缩 + 按秩合并,否则最坏查询接近 O(log V),整体变慢
  • 边数少于 V-1 时直接返回空,图不连通,不存在最小生成树

怎么写一个高效的并查集辅助克鲁斯卡尔

别用 map 或 set 实现 parent,用 std::vector<int></int> 下标即节点编号(假设节点编号为 0 到 V-1)。初始化时 parent[i] = i,rank[i] = 0。

关键点在于 find 必须带路径压缩,unionSets 必须按秩合并——否则在稠密测试用例(如 1e5 条边)下会 TLE 或 WA。

C++ Code Review Master
C++ Code Review Master

组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

下载
  • find(x) 返回根,并把沿途所有节点父指针直接连到根
  • unionSets(x, y) 只在两根不同时才合并,且小树挂到大树下(用 rank 判断)
  • 返回 true 表示成功合并(即无环),false 表示已连通(加这条边会成环)

std::sort 边时容易踩的坑

错误写法:sort(edges.begin(), edges.end(), [](auto& a, auto& b) { return get(a) (b); }); 看似没问题,但若权值相同,后续行为不可控——不同 STL 实现可能打乱原始顺序,导致本该选的边被跳过。

更稳妥的做法是三元组排序时加次级键(比如节点编号),保证稳定:

sort(edges.begin(), edges.end(), [](const auto& a, const auto& b) {
    if (get(a) != get(b)) return get(a) (b);
    if (get(a) != get(b)) return get(a) (b);
    return get(a) (b);
});
  • 不加次级键不影响正确性,但影响可复现性(尤其调试时)
  • 如果输入边本身已按权值有序,仍建议调用 sort——别依赖输入顺序
  • 避免用 float 或 double 作权值参与比较,浮点误差可能让相等权值被误判大小

完整流程中常被忽略的边界检查

很多人写完核心循环就交,但实际运行时崩溃或输出错误,往往卡在这些地方:

  • 节点编号是否从 0 开始?若输入是 1-indexed,记得建并查集时 size 设为 V+1,且所有 u, v 减 1
  • 输入含重边?克鲁斯卡尔本身能处理,但若手动去重反而可能删掉权值小的那条,应保留所有边让 sort 自行选择
  • 权值为负?算法支持,但需确认题意是否允许(负权边在 MST 中合法,不影响 Kruskal 正确性)
  • 最后生成的边数不是 V-1?说明图不连通,此时应返回空集或报错,而不是强行凑满

最麻烦的是节点编号稀疏(比如只有 1、100、10000),但你按最大编号分配了 1e5 大小的 parent 数组——内存浪费且易越界。真遇到这种,先离散化节点编号再做并查集。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

2024.04.28

6267

8

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

2025.10.23

724

4

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

2023.09.04

1138

7

c语言union的用法
c语言union的用法

c语言union的用法是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型,union的使用可以帮助我们节省内存空间,并且可以方便地在不同的数据类型之间进行转换。使用union时需要注意对应的成员是有效的,并且只能同时访问一个成员。本专题为大家提供union相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.27

669

5

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

6059

3

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.08.29

2965

6

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

3788

10

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.29

2665

10

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

3788

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习