c++如何实现Prim算法最小生成树_c++ 邻接矩阵与贪心策略选择【实战】

发布时间 - 2025-12-29 00:00:00    点击率:
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看作另一侧——此时连接SV\S的最小边必然可安全加入。

  • 这个性质不依赖边权是否为正,但要求图连通;若不连通,key[v]最终仍为INT_MAX,可据此判断
  • 如果图含负权边,Prim依然成立(不同于Dijkstra),因为不涉及路径累加,只比单条边权
  • 但邻接矩阵中用0表示无边时,必须确保真实边权≠0;否则要改用-1INT_MAX作无效标记

邻接矩阵Prim的时间复杂度和优化边界

标准实现是O(n²):外层循环n次,每次找最小keyO(n),更新邻居也耗O(n)。这比堆优化版(O(m log n))在稀疏图中慢,但在稠密图(m ≈ n²)下两者接近,且邻接矩阵常数更小、代码更稳。

真正要注意的是内存和初始化开销:

  • graph二维vector大小为n × nn=10⁴时就需约400MB内存(int占4字节),直接爆掉
  • 若实际边数很少,强行用邻接矩阵纯属浪费;应切到邻接表+priority_queue
  • 初始化keyvector(n, INT_MAX)没问题,但别用memset(key, 0x3f, sizeof(key))——它按字节赋值,对int可能不等于0x3f3f3f3f

调试时最常见的三个错误现象

写完跑不对?先盯这三个地方:

  • 邻接矩阵中用0表示“无边”,但某条合法边权恰好是0 → 更新时if (graph[u][v] != 0)会跳过它。解决:统一用-1INT_MAX作无效标记,或额外存valid标志
  • parent[v] = u写成parent[u] = v → 最终输出的边反向,生成树结构错乱
  • 没重置inMSTkey就复用同一组变量跑多组数据 → 上一轮残留状态污染结果

邻接矩阵Prim看似简单,但初始化语义、无效值约定、索引方向这三点,几乎包揽了90%的本地调试失败原因。


# 字节  # c++  # 为什么  # if  # int  # 循环  #   # Property  # 算法  # 子树  # 的是  # 都在  # 不多  # 设为  # 但在  # 要注意  # 时就  # 再用  # 这三个 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  详解jQuery中的事件  韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南  Laravel如何为API生成Swagger或OpenAPI文档  Laravel Docker环境搭建教程_Laravel Sail使用指南  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  js代码实现下拉菜单【推荐】  夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化  jQuery validate插件功能与用法详解  Laravel如何处理CORS跨域请求?(配置示例)  Laravel如何与Docker(Sail)协同开发?(环境搭建教程)  java中使用zxing批量生成二维码立牌  Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)  Android仿QQ列表左滑删除操作  Android实现代码画虚线边框背景效果  如何用5美元大硬盘VPS安全高效搭建个人网站?  如何快速生成专业多端适配建站电话?  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  详解阿里云nginx服务器多站点的配置  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  韩国服务器如何优化跨境访问实现高效连接?  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  Laravel怎么连接多个数据库_Laravel多数据库连接配置  如何在 Go 中优雅地映射具有动态字段的 JSON 对象到结构体  北京网页设计制作网站有哪些,继续教育自动播放怎么设置?  Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】  如何获取PHP WAP自助建站系统源码?  UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】  如何在IIS中新建站点并配置端口与物理路径?  晋江文学城电脑版官网 晋江文学城网页版直接进入  如何用虚拟主机快速搭建网站?详细步骤解析  Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程  Windows11怎样设置电源计划_Windows11电源计划调整攻略【指南】  INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】  Python并发异常传播_错误处理解析【教程】  JavaScript中的标签模板是什么_它如何扩展字符串功能  ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法  教学论文网站制作软件有哪些,写论文用什么软件 ?  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  如何用wdcp快速搭建高效网站?  SQL查询语句优化的实用方法总结  原生JS实现图片轮播切换效果  浅析上传头像示例及其注意事项  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  JavaScript模板引擎Template.js使用详解  如何自定义建站之星模板颜色并下载新样式?  Laravel如何为API编写文档_Laravel API文档生成与维护方法