Bellman-Ford(贝尔曼福特算法)

简介

贝尔曼-福特算法(Bellman-Ford Algorithm)是一种用于求解单源最短路径问题的算法,它可以处理带有负权边的图。 该算法的实现思路是通过不断迭代松弛操作来更新最短路径,直到找到最优解。

名词解释:
1. 松弛操作:不断更新最短路径和前驱结点的操作。
2. 负权回路:绕一圈绕回来发现到自己的距离从0变成了负数,到各结点的距离无限制的降低,停不下来

算法特点

  • 贝尔曼-福特算法可以处理带有负权边的图,而迪杰斯特拉算法(Dijkstra's Algorithm)等其他最短路径算法无法处理这种情况。
  • 贝尔曼-福特算法的实现相对简单,易于理解和编程。
  • 贝尔曼-福特算法的时间复杂度为 O(nm),其中 n 是图中顶点的个数,m 是图中边的个数。 这使得它在稀疏图中效率较低。

如何理解贝尔曼-福特算法?

想象一下你正在一个城市中寻找最短路径。 你可以从一个路口开始,沿着道路前进,并记录下每个路口的距离。 贝尔曼-福特算法的工作方式类似:

  • 首先,将所有路口的距离设置为无穷大,并将起点距离设置为 0。

  • 然后,遍历所有道路,并对每个路口进行以下操作:

    • 如果当前路口的距离加上该道路的长度小于该道路终点的距离,则将该道路终点的距离更新为当前路口的距离加上该道路的长度。
  • 重复上述步骤 n - 1 次,其中 n 是路口的数量。

通过不断重复上述步骤,最终可以找到所有路口到起点的最短路径。

代码

void ford() {// 初始化距离数组,表示起点到每个顶点的距离为无穷大for (int i = 1; i <= n; i++) {dis[i] = INF;}dis[1] = 0; // 起点到自身的距离为0// 进行n-1次松弛操作for (int k = 1; k <= n - 1; k++) {for (int i = 1; i <= m; i++) {// 如果通过当前边能够使终点的距离更短,则更新距离if (dis[v[i]] > dis[u[i]] + w[i]) {dis[v[i]] = dis[u[i]] + w[i];}}}
}

如有不理解的可以上b站上看up主@简枫叶

总结

Bellman算法的核心就是松驰,没有贪心策略,也使它的时间复杂度比较高。因为它是单纯的松驰。首先我们要明白的是:如果处于第n层的节点,在它上一层的即n-1层所以节点的dist已经确定为最终真实值,那么通过一次遍历,第n层节点的dist也能被确定为最终真实值。第一次迭代,获得的信息是:与源点相邻点的真正dist(第二层节点),(其他点的可能仍为无穷大,或者为松驰一次状态);第二次循环,因为第二层的信息已经完全掌握,此次迭代是能确定第三层节点(从源点出发,经过2条边)的点的真实最短距离。(由于遍历的过程中,只完全掌握了第一层,其他节点的dist不能完全确定为最终的dist);如此循环,遍历n-1次,第n层的节点已经遍历完,至此,所有节点的dist都最终确定了(解释了为啥能求最短路)

例题P1629 邮递员送信

 邮递员送信

 题目描述

有一个邮递员要送东西,邮局在节点 1。他总共要送 n-1 样东西,其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n-1 样东西并且最终回到邮局最少需要的时间。

 输入格式

第一行包括两个整数,n 和 m,表示城市的节点数量和道路数量。

第二行到第 (m+1) 行,每行三个整数,u,v,w,表示从u 到 v 有一条通过时间为 w 的道路。

 输出格式

输出仅一行,包含一个整数,为最少需要的时间。

#include <stdio.h>#define INF 99999999 // 定义无穷大值
#define MAXN 1005 // 最大顶点数
#define MAXM 100005 // 最大边数int n, m; // 顶点数和边数
int u[MAXM], v[MAXM], w[MAXM]; // 边的起点、终点、权值
int dis[MAXN]; // 存储起点到各顶点的最短距离// 初始化函数,读入顶点数、边数以及每条边的起点、终点、权值
void init() {scanf("%d %d", &n, &m); // 输入顶点数n和边数mfor (int i = 1; i <= m; i++) {scanf("%d %d %d", &u[i], &v[i], &w[i]); // 输入每条边的起点、终点、权值}
}// 反转边的起点和终点
void over() {for (int i = 1; i <= m; i++) {int temp = u[i];u[i] = v[i];v[i] = temp;}
}// Ford算法求解最短路径
void ford() {// 初始化距离数组,表示起点到每个顶点的距离为无穷大for (int i = 1; i <= n; i++) {dis[i] = INF;}dis[1] = 0; // 起点到自身的距离为0// 进行n-1次松弛操作for (int k = 1; k <= n - 1; k++) {for (int i = 1; i <= m; i++) {// 如果通过当前边能够使终点的距离更短,则更新距离if (dis[v[i]] > dis[u[i]] + w[i]) {dis[v[i]] = dis[u[i]] + w[i];}}}
}int main() {init(); // 初始化int ans = 0; // 记录总距离ford(); // 调用Ford算法计算从起点到各顶点的最短距离for (int i = 1; i <= n; i++) {ans += dis[i]; // 累加起点到各顶点的最短距离}over(); // 反转边的起点和终点ford(); // 重新计算最短路径for (int i = 1; i <= n; i++) {ans += dis[i]; // 累加起点到各顶点的最短距离}printf("%d\n", ans); // 输出总距离return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/697110.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt 获取控件尺寸与实际不一致的问题

前提&#xff1a;界面ui获取桌面大小&#xff0c;用resize() 重新调整了界面尺寸 然后 我获取界面上某个控件大小时&#xff0c;发现与实际尺寸不一样。 最后发现&#xff1a; 获取控件大小的地方&#xff0c;必须在界面show()之后才可以&#xff0c;放之前不行。 注意; 经…

WPF 控件禁用时,显示悬浮提示

WPF 控件禁用时&#xff0c;显示悬浮提示 控件在禁用状态下&#xff0c;按钮是没有悬浮提示信息的&#xff0c;是事件触发的机制&#xff1b; 如果要禁用下也有悬浮提示&#xff0c;可以在控件外面加一层&#xff0c;例如&#xff1a; <Border Grid.Column"1" To…

Hive【内部表、外部表、临时表、分区表、分桶表】【总结】

目录 Hive的物种表结构特性 一、内部表 建表 使用场景 二、外部表 建表:关键词【EXTERNAL】 场景&#xff1a; 外部表与内部表可互相转换 三、临时表 建表 临时表横向对比​编辑 四、分区表 建表&#xff1a;关键字【PARTITIONED BY】 场景&#xff1a; 五、分桶表 …

CentOS 7.x 使用 RPM 包安装 Gitlab

官网&#xff1a;https://about.gitlab.com/ https://about.gitlab.cn/install/ 安装&#xff1a;https://gitlab.cn/install/ 博客&#xff1a;https://gitlab.cn/blog/ 文档&#xff1a;https://docs.gitlab.com/ https://about.gitlab.com/install/#centos-7 https://docs.g…

工作记录vue3 echarts地图等 监听浏览器等写法

子组件<template><div><div>【云端报警风险】</div><div ref"target" class"w-full h-full"></div></div> </template><script setup> import { ref, onMounted,watch } from vue; import * as ech…

算能RISC-V通用云开发空间编译pytorch @openKylin留档

终于可以体验下risc-v了&#xff01; 操作系统是openKylin&#xff0c;算能的云空间 尝试编译安装pytorch 首先安装git apt install git 然后下载pytorch和算能cpu的库&#xff1a; git clone https://github.com/sophgo/cpuinfo.git git clone https://github.com/pytorc…

小米14 Ultra:未来科技的集大成者

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

opencv图像的本质

目的 OpenCV是一个跨平台的库&#xff0c;使用它我们可以开发实时的计算机视觉应用程序。 它主要集中在图像处理&#xff0c;视频采集和分析&#xff0c;包括人脸检测和物体检测等功能。 数字图像在计算机中是以矩阵形式存储的&#xff0c;矩阵中的每一个元素都描述一定的图像…

VSCode React JavaScript Snippets 插件的安装与使用指南

VSCode React JavaScript Snippets 插件的安装与使用指南 在开发 React 项目时&#xff0c;提高效率是每个开发者都追求的目标之一。VSCode React JavaScript Snippets 插件就是为了提升 React 开发效率而设计的&#xff0c;它为常用的 React 代码片段提供了快捷键&#xff0c;…

NXP实战笔记(六):S32K3xx基于RTD-SDK在S32DS上配置PWM发波

目录 1、概述 2、SDK配置 2.1、Port配置 2.2、Emios_Mcl_Ip 2.3、Emios_Pwm 2.4、代码示例 1、概述 针对S32K3xx芯片&#xff0c;产生PWM的硬件支持单元仅有两个&#xff0c;分别是eMiosx与Flexio. 生成PWM的顺序&#xff0c;按照单片机所用资源进行初始化执行如下 初始化…

去年面试的运维开发面试题二

VPN有哪些协议&#xff0c;不同协议之间有何区别&#xff1f; 2.内部组网通常使用哪些类型的网段&#xff0c;两个不同网段如何通信&#xff1f; 3.Linux中绝对路径&#xff0c;相对路径的区别 4. Linux如何添加磁盘&#xff0c;扩容系统文件&#xff1f; 5. Linux如何查看进程…

原型模式(Prototype Pattern) C++

上一节&#xff1a;建造者模式&#xff08;Builder Pattern&#xff09;C 文章目录 0.理论1.原型模式的核心组成&#xff1a;2.实现方法3.什么时候使用 1.实践步骤 1: 定义怪物原型步骤 2: 实现具体怪物原型步骤 3: 使用原型创建怪物 0.理论 原型模式&#xff08;Prototype P…

7-liunx服务器规范

目录 概况liunx日志liunx系统日志syslog函数openlog 可以改变syslog默认输出方式 &#xff0c;进一步结构化 用户信息进程间的关系会话ps命令查看进程关系 系统资源限制改变工作目录和根目录服务器程序后台话 概况 liunx服务器上有很多细节需要注意 &#xff0c;这些细节很重要…

服务网格Service Mesh和Istio

文章目录 服务网格&#xff08;Service Mesh&#xff09;市场上三种服务网格解决方案服务网格的特征流量管理安全性可观察性 Istio简介Istio提供了什么功能服务 &#xff1f;Istio 核心特性流量管理安全可观察性 平台支持 服务网格&#xff08;Service Mesh&#xff09; 服务网…

Eureka注册中心(黑马学习笔记)

Eureka注册中心 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图&#xff1a; 大家思考几个问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址和端口&#xff1f; 有多个user-service实例地址&#xff0c…

六、行列式基本知识

目录 1、行列式的特性 2、行列式的计算方法: 2.1 通过行列式的定义去计算:对角法则。 2. 2 利用行列式的性质将行列式转化为上三角行列式: ①行列式的性质 : 性质一: 性质二: 性质三: 性质四:行列式之间的加法

TreeData 数据查找

TreeData 数据查找 最近做需求的时候遇到了这样的一个需求&#xff0c;Tree组件数据支持查找&#xff0c;而且TreeData的数据层级是无限级的 开始想的事借助UI组件库&#xff08;Ant-design-vue&#xff09;中的Tree组件的相关方法直接实现,看了下api 发现没法实现&#xff0c;…

超级实用的python代码片段汇总和详细解析(16个)

目录 1. 生成随机文本 2. 计算文本文件中的字数 3. 替换文件文件中的字串 4. 多文件名的批量替换 5. 从网站提取数据 6. 批量下载图片 7.批量删除空文件夹 8.Excel表格读写 9.合并Excel表格工作簿 10.数据库SQL查询 11. 系统进程查杀 12.图像尺寸调整和裁剪 13.图…

redis实现消息队列redis发布订阅redis监听key

文章目录 Redis消息队列实现异步秒杀1. jvm阻塞队列问题2. 什么是消息队列3. Redis实现消息队列1. 基于List结构模拟消息队列操作优缺点 2. 基于PubSub发布订阅的消息队列操作优缺点spring 结合redis的pubsub使用示例1. 引入依赖2. 配置文件3. RedisConfig4. CustomizeMessageL…

大语言模型的开山之作—探秘GPT系列:GPT-1-GPT2-GPT-3的进化之路

模型模型参数创新点评价GPT1预训练微调&#xff0c; 创新点在于Task-specific input transformations。GPT215亿参数预训练PromptPredict&#xff0c; 创新点在于Zero-shotZero-shot新颖度拉满&#xff0c;但模型性能拉胯GPT31750亿参数预训练PromptPredict&#xff0c; 创新点…