编程语言
首页 > 编程语言> > Bellman Ford 算法

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行

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

标签:int,短路,Bellman,Ford,算法,号点
来源: https://www.cnblogs.com/XiaoHei666/p/16492358.html