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/)。

点的编号为 /(1∼n/)。

输出格式

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

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

输入样例:

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

输出样例:

3

数据范围

/(1≤n,k≤500,/)

/(1≤m≤10000,/)

/(1≤x,y≤n,/)

任意边长的绝对值不超过 /(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行

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

原创文章,作者:3628473679,如若转载,请注明出处:https://blog.ytso.com/275290.html

(0)
上一篇 2022年7月19日
下一篇 2022年7月19日

相关推荐

发表回复

登录后才能评论