c++怎么实现贝尔曼-福特算法_c++ 负权边处理与最短路径计算【案例】

发布时间 - 2026-01-06 00:00:00    点击率:
贝尔曼-福特算法核心是通过n-1轮松弛操作,用所有边逐轮更新最短距离,可处理负权边但无法处理负权环;C++实现需用LLONG_MAX/2初始化、检测更新提前终止,并通过第n轮判断可达负权环。

贝尔曼-福特算法的核心逻辑是什么

贝尔曼-福特算法本质是通过 n-1 轮松弛操作,逐步逼近每个节点到源点的最短距离;它能处理含负权边的图,但不能处理存在负权环的图(否则最短路径无定义)。关键不在于“多轮迭代”,而在于每轮都尝试用所有边更新距离——这保证了即使最远路径需要经过 n-1 条边,也能在第 n-1 轮被收敛。

如何用 C++ 实现标准版 Bellman-Ford

使用 vector> 存储边(起点、终点、权重),配合 vector 维护距离数组。注意初始化为 LLONG_MAX / 2(避免后续加法溢出),源点设为 0

#include 
#include 
#include 
#include 
using namespace std;

vector bellman_ford(int n, vector>& edges, int src) { vector dist(n, LLONG_MAX / 2); dist[src] = 0;

for (int i = 0; i zuojiankuohaophpcn n - 1; ++i) {
    bool updated = false;
    for (auto& [u, v, w] : edges) {
        if (dist[u] != LLONG_MAX / 2 && dist[u] + w zuojiankuohaophpcn dist[v]) {
            dist[v] = dist[u] + w;
            updated = true;
        }
    }
    if (!updated) break; // 提前终止
}

return dist;

}

  • n 是顶点数(编号从 0n-1
  • 边列表可含重复或反向边,不影响正确性
  • 提前终止条件(updated == false)对稀疏图很有效,但不能跳过第 n-1 轮检测负环

怎么检测图中是否存在负权环

运行完 n-1 轮松弛后,再执行一轮:若任意边仍能更新距离,则说明存在从源点可达的负权环。注意——只检测“从源点出发能到达的负环”,孤立负环不会触发。

立即学习“C++免费学习笔记(深入)”;

bool has_negative_cycle(int n, vector>& edges, int src) {
    vector dist(n, LLONG_MAX / 2);
    dist[src] = 0;
for (int i = 0; i zuojiankuohaophpcn n - 1; ++i) {
    for (auto& [u, v, w] : edges) {
        if (dist[u] != LLONG_MAX / 2 && dist[u] + w zuojiankuohaophpcn dist[v]) {
            dist[v] = dist[u] + w;
        }
    }
}

// 第 n 轮检测
for (auto& [u, v, w] : edges) {
    if (dist[u] != LLONG_MAX / 2 && dist[u] + w zuojiankuohaophpcn dist[v]) {
        return true;
    }
}
return false;

}

  • 必须用同一套 dist 数组连续跑 n 轮,不能重置
  • 若只需判断负环存在性,无需保存中间距离,可省去提前终止
  • 若图不连通,且负环不在源点连通分量内,该函数返回 false ——这是预期行为,不是 bug

实际使用时最容易踩的坑

负权边本身不危险,危险的是没意识到 Bellman-Ford 的“可达性前提”和整数溢出风险。

  • 输入边时忘记检查 uv 是否在 [0, n) 范围内,导致越界访问
  • INT_MAX 初始化 dist,遇到负权边做加法时直接溢出成负数,后续比较全乱
  • 误以为返回 LLONG_MAX / 2 就代表“不可达”,其实应判断是否仍等于初始值(因为负权路径可能真达到极大正值)
  • 多源点场景下直接复用单源实现,结果只算出一个源点的结果——Bellman-Ford 本就是单源算法,多源需多次调用或改用 Floyd

负权边能算,但得确保你真正需要它;多数业务场景里,出现负权往往意味着建模错误,先确认是不是权重含义理解反了,比急着写松弛更关键。


# edge  # c++  # ios  # stream  # int  # 算法  # bug  # 源点  # 贝尔  # 福特  # 可达  # 最短  # 标准版  # 的是  # 这是  # 很有  # 只需 


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


相关推荐: Python结构化数据采集_字段抽取解析【教程】  C#如何调用原生C++ COM对象详解  Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  高性价比服务器租赁——企业级配置与24小时运维服务  Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  Laravel如何与Pusher实现实时通信?(WebSocket示例)  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  EditPlus中的正则表达式 实战(4)  如何在宝塔面板创建新站点?  Laravel怎么配置S3云存储驱动_Laravel集成阿里云OSS或AWS S3存储桶【教程】  iOS UIView常见属性方法小结  Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询  夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化  php 三元运算符实例详细介绍  Laravel DB事务怎么使用_Laravel数据库事务回滚操作  如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】  Python数据仓库与ETL构建实战_Airflow调度流程详解  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  如何用AI帮你把自己的生活经历写成一个有趣的故事?  魔方云NAT建站如何实现端口转发?  如何用wdcp快速搭建高效网站?  Mybatis 中的insertOrUpdate操作  北京的网站制作公司有哪些,哪个视频网站最好?  jquery插件bootstrapValidator表单验证详解  如何用已有域名快速搭建网站?  Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解  如何在景安云服务器上绑定域名并配置虚拟主机?  Laravel如何正确地在控制器和模型之间分配逻辑_Laravel代码职责分离与架构建议  Linux安全能力提升路径_长期防护思维说明【指导】  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  非常酷的网站设计制作软件,酷培ai教育官方网站?  iOS正则表达式验证手机号、邮箱、身份证号等  制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?  高端智能建站公司优选:品牌定制与SEO优化一站式服务  Laravel API资源类怎么用_Laravel API Resource数据转换  打造顶配客厅影院,这份100寸电视推荐名单请查收  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  iOS验证手机号的正则表达式  laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程  安克发布新款氮化镓充电宝:体积缩小 30%,支持 200W 输出  Internet Explorer官网直接进入 IE浏览器在线体验版网址  如何有效防御Web建站篡改攻击?  在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?  Laravel如何实现模型的全局作用域?(Global Scope示例)  如何快速搭建二级域名独立网站?  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?