Bellman-Ford算法适用于单源最短路径问题(即求源结点到所有其他顶点的最短路径),使用注意事项:
(1)可以有负权边,但不能有负环
(2)适用于所有类型的图
存储结构采用边结构体数组,n
为顶点数,m
为边数
struct edge {
int a, b, w;
}graph[m];
若源结点为顶点s
,dis[i]
标示源结点s
到顶点i
的最短距离(初始化dis[s]
为0
,其他为0x3f3f3f3f
),为了防止串连,每轮循环开始前用bak
数组备份dis
数组
int dis[n], bak[n];
对于有向图中的某条边(起点a
,终点b
,边权w
),若满足dis[b]
$\leqslant$ dis[a] + w
,称该边满足三角形不等式。如果有向图所有边都满足三角形不等式,则dis数组就是所求最短路径
Bellman-Ford算法对每条边进行松弛操作,使其满足三角形不等式,算法流程如下:
(1)扫描所有边e
,进行松弛操作(若dis[e.b] < bak[e.a] + e.w
,则用bak[e.a] + e.w
更新dis[e.b]
)
(2)重复上述步骤n-1
次(循环k
次后,dis
数组中存储经过不超过k
条边的单源最短路径,n
个顶点的路径最多n-1
条边,循环n-1
次即可)
for (int i = 0; i < k; i++) {
memcpy(bak, dis, sizeof(bak));
for (int j = 0; j < m; j ++ ) {
auto e = graph[j];
dis[e.b] = min(dis[e.b], bak[e.a] + e.w);
}
}
算法结束时,dis[i]
存储源结点s
到顶点i
的最短距离,dis[i] > 0x3f3f3f3f/2
表明顶点i
不可达(由于对图中所有边进行松弛操作并且有负权边,就算s
和i
不连通,dis[i]
也可能被更新)
注解:Bellman-Ford算法循环k
次后的dis
数组存储经过不超过k
条边的单源最短路径,如果要求经过不超过k
条边的单源最短路径只能用Bellman-Ford算法