c++如何实现Prim算法最小生成树_c++ 邻接矩阵与贪心策略选择【实战】
技术百科
冰火之心
发布时间:2025-12-29
浏览: 次 Prim算法用邻接矩阵实现需初始化key[0]=0、其余INT_MAX,每次选未入树且key最小的顶点u,再更新其邻接点v的key和parent;贪心正确性源于MST切割性质,支持负权边,时间复杂度O(n²),稠密图适用,但需避免0误判无边、索引错位及状态残留。
Prim算法在C++中用邻接矩阵怎么写
邻接矩阵是Prim算法最直观的实现方式,尤其适合顶点数不多(比如 n ≤ 1000)的稠密图。核心思路是维护一个key[]数组记录每个顶点到当前生成树的最小边权,再用inMST[]标记是否已加入生成树。
关键点不是“能不能写”,而是初始化和更新逻辑容易出错:比如key[0]必须设为0(从顶点0开始),其余初始化为INT_MAX;每次选key最小且未入树的顶点时,必须检查!inMST[u],否则会重复选取。
vector> graph = { {0, 2, 0, 6, 0}, {2, 0, 3, 8, 5}, {0, 3, 0, 0, 7}, {6, 8, 0, 0, 9}, {0, 5, 7, 9, 0} }; int n = graph.size(); vector key(n, INT_MAX); vector inMST(n, false); vector parent(n, -1); key[0] = 0; for (int i = 0; i < n; i++) { int u = -1; for (int j = 0; j < n; j++) if (!inMST[j] && (u == -1 || key[j] < key[u])) u = j; inMST[u] = true; for (int v = 0; v < n; v++) if (graph[u][v] != 0 && !inMST[v] && graph[u][v] < key[v]) { key[v] = graph[u][v]; parent[v] = u; } }
为什么贪心选择“当前最小边”不会错过全局最优
Prim的贪心正确性依赖于MST的切割性质(cut property):对任意切割,横跨该切割的最小权重边一定属于某棵MST。算法每一步都在维护一个已构建的子树集合S,把V\S看作另一侧——此时连接S与V\S的最小边必然可安全加入。
- 这个性质不依赖边权是否为正,但要求图连通;若不连通,
key[v]最终仍为INT_MAX,可据此判断 - 如果图含负权边,Prim依然成
立(不同于Dijkstra),因为不涉及路径累加,只比单条边权 - 但邻接矩阵中用
0表示无边时,必须确保真实边权≠0;否则要改用-1或INT_MAX作无效标记
邻接矩阵Prim的时间复杂度和优化边界
标准实现是O(n²):外层循环n次,每次找最小key耗O(n),更新邻居也耗O(n)。这比堆优化版(O(m log n))在稀疏图中慢,但在稠密图(m ≈ n²)下两者接近,且邻接矩阵常数更小、代码更稳。
真正要注意的是内存和初始化开销:
-
graph二维vector大小为n × n,n=10⁴时就需约400MB内存(int占4字节),直接爆掉 - 若实际边数很少,强行用邻接矩阵纯属浪费;应切到邻接表+priority_queue
- 初始化
key用vector没问题,但别用(n, INT_MAX) memset(key, 0x3f, sizeof(key))——它按字节赋值,对int可能不等于0x3f3f3f3f
调试时最常见的三个错误现象
写完跑不对?先盯这三个地方:
- 邻接矩阵中用
0表示“无边”,但某条合法边权恰好是0 → 更新时if (graph[u][v] != 0)会跳过它。解决:统一用-1或INT_MAX作无效标记,或额外存valid标志 -
parent[v] = u写成parent[u] = v→ 最终输出的边反向,生成树结构错乱 - 没重置
inMST或key就复用同一组变量跑多组数据 → 上一轮残留状态污染结果
邻接矩阵Prim看似简单,但初始化语义、无效值约定、索引方向这三点,几乎包揽了90%的本地调试失败原因。
# 的是
# 都在
# 时就
# 但在
# 这三个
# 要注意
# 不多
# 设为
# 再用
# 循环
# 堆
# Property
# c++
# if
# int
# 字节
# 为什么
# 算法
# 子树
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么开启远程桌面_Win11系统远程桌面
- Win11怎么格式化U盘_Win11系统U盘格式化
- PHP主流架构如何处理会话管理_Session与C
- Win11怎么清理C盘系统错误报告_Win11清理
- 如何诊断并终止卡死的 multiprocessin
- php485在php5.6下能用吗_php485旧
- Windows10如何更改系统字体大小_Win10
- 如何使用Golang编写单元测试_创建Test函数
- Win11如何设置自动关机 Win11定时关机命令
- c++输入输出流 c++ cin与cout格式化输
- Python文本编码与解码_跨平台解析说明【指导】
- 如何使用 Python 合并文件夹内多个 Exce
- Win11怎么禁用键盘自带键盘_Win11笔记本禁
- 如何在 Go 中创建包含映射(map)的切片(sl
- 如何在Golang中编写异步函数测试_Golang
- php下载安装包太大怎么下载_分卷压缩下载方法【教
- php中$this和::能混用吗_对象与静态作用域
- Win11如何暂停系统更新 Win11暂停更新最长
- Go 中 defer 在 goroutine 内部
- Win11怎么设置任务栏图标大小_Windows1
- Windows 11如何开启文件夹加密(EFS)_
- 如何更改Windows资源管理器的默认启动位置?(
- Win11如何设置鼠标灵敏度_Win11鼠标灵敏度
- 如何使用正则表达式精确匹配最多含一个换行符的 st
- Python音视频处理高级项目教程_FFmpegP
- PythonPandas数据分析项目教程_时间序列
- 如何高效删除 NumPy 二维数组中所有元素相同的
- PHP主流架构如何做单元测试_工具与流程【详解】
- Win11无法识别耳机怎么办_解决Win11插耳机
- Python项目回滚策略_发布安全说明【指导】
- 如何使用Golang模拟请求超时_Golang c
- Windows系统时间服务错误_W32Time服务
- Win11如何关闭游戏模式 Win11禁用Xbox
- 如何在 Windows 11 中使用 AlomWa
- ACF 教程:正确更新嵌套在多层 Group 字段
- Win11文件夹预览图不显示怎么办_Win11缩略
- 使用类变量定义字符串常量时的类型安全最佳实践
- Python解释执行模型_字节码流程说明【指导】
- 如何使用正则表达式批量替换重复的星号-短横模式为固
- Win10如何卸载Skype_Win10卸载Sky
- Windows如何拦截2345弹窗广告_Windo
- Win11怎么修复系统文件_使用sfc命令修复Wi
- Win11怎么激活Windows10_Win11激
- 如何使用Golang sort排序切片_Golan
- 如何关闭Win10自动更新更新_Win10系统自动
- 短链接怎么用php递归还原_多层加密链接的处理法【
- c++怎么使用std::filesystem遍历文
- php和redis连接超时怎么办_phpredis
- Win11怎样安装钉钉客户端_Win11安装钉钉教
- Win10怎样卸载DockerDesktop_Wi

立(不同于Dijkstra),因为不涉及路径累加,只比单条边权
QQ客服