Bellman Ford 算法

Bellman Ford算法

1.最短路问题

在图论中,最短路问题分为单源最短路和多源最短路。

其中,单源最短路又分为存在负权边和不存在负权边两种。

Bellman Ford算法就是来解决存在负权边的最短路问题的。

2.Bellman Ford算法介绍

简称Ford(福特)算法,同样是用来计算从一个点到其他所有点的 最短路径的算法,也是一种单源最短路径算法。

能够处理存在负边权的情况,但无法处理存在负权回路的情况(下文会有详细说明)。

算法时间复杂度:O(nm)n 是顶点数,m 是边数。

3.Bellman Ford算法经典题目

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。

请你求出从 1 号点到 n 号点的最多经过 k 条边的最短距离,如果无法从 1 号点走到 n 号点,输出 impossible。

注意:图中可能存在负权回路

输入格式

第一行包含三个整数 n,m,k

接下来 m 行,每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z

点的编号为 1n

输出格式

输出一个整数,表示从 1 号点到 n 号点的最多经过 k 条边的最短距离。

如果不存在满足条件的路径,则输出 impossible

输入样例:

3 3 1
1 2 1
2 3 1
1 3 3

输出样例:

3

数据范围

1n,k500,

1m10000,

1x,yn,

任意边长的绝对值不超过 10000

4.Bellman Ford算法思路

Bellman Ford算法的存储方式很自由,不用非得用邻接矩阵、邻接表,只要有每条边的开始节点、终止节点和权值就行。

所以,开个存边的结构体就够。

剩下的都在代码注释里,请自行查阅。

5.Bellman Ford算法代码

#include<iostream>
#include<cstring>
using namespace std;
const int M=100005,N=505;
int n,m,k;
int d[N],bc[N];//d数组是存储最短路,bc是 d的备份
struct Edge{
int a,b,w;//存在一条从点 a 到点 b 的有向边,边长为 w
}edge[M];
int ford(){
memset(d,0x3f,sizeof(d));//初始化为正无穷
d[1]=0;//第一个节点到第一个节点的最短路为 0
for(int i=0;i<k;i++){//因为最多只能经过k条边,所以只能循环k次
memcpy(bc,d,sizeof(d));//做备份,防止串联
for(int j=0;j<m;j++){ //遍历每条边
int a=edge[j].a,b=edge[j].b,w=edge[j].w;
d[b]=min(d[b],bc[a]+w);//这里跟Dijkstra算法非常像,都是比较原始最短路和新路的长度
}
}
if(d[n]==0x3f3f3f3f) return 0x3f3f3f3f;//不能return-1,如果答案是-1那也会输出错误
return d[n];
}
int main(){
cin>>n>>m>>k;
for(int i=0;i<m;i++)
cin>>edge[i].a>>edge[i].b>>edge[i].w;
if(ford()==0x3f3f3f3f) cout<<"impossible";
else cout<<d[n];
return 0;
}

完awa~

90行

如果觉得还不错就给个赞吧,您的支持是本蒟蒻最大的动力。

posted @   Rainforests  阅读(196)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示