https://www.cnblogs.com/gaochundong/p/bellman_ford_algorithm.html
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法。该算法由 Richard Bellman 和 Lester Ford 分别发表于 1958 年和 1956 年,而实际上 Edward F. Moore 也在 1957 年发布了相同的算法,因此,此算法也常被称为 Bellman-Ford-Moore 算法。
Bellman-Ford 算法和 Dijkstra 算法同为解决单源最短路径的算法。对于带权有向图 G = (V, E),Dijkstra 算法要求图 G 中边的权值均为非负,而 Bellman-Ford 算法能适应一般的情况(即存在负权边的情况)。一个实现的很好的 Dijkstra 算法比 Bellman-Ford 算法的运行时间要低。
Bellman-Ford 算法采用动态规划(Dynamic Programming)进行设计,实现的时间复杂度为 O(V*E),其中 V 为顶点数量,E 为边的数量。Dijkstra 算法采用贪心算法(Greedy Algorithm)范式进行设计,普通实现的时间复杂度为 O(V2),若基于 Fibonacci heap 的最小优先队列实现版本则时间复杂度为 O(E + VlogV)。
Bellman-Ford 算法描述:
- 创建源顶点 v 到图中所有顶点的距离的集合 distSet,为图中的所有顶点指定一个距离值,初始均为 Infinite,源顶点距离为 0;
- 计算最短路径,执行 V - 1 次遍历;
- 对于图中的每条边:如果起点 u 的距离 d 加上边的权值 w 小于终点 v 的距离 d,则更新终点 v 的距离值 d;
- 检测图中是否有负权边形成了环,遍历图中的所有边,计算 u 至 v 的距离,如果对于 v 存在更小的距离,则说明存在环;
伪码实现如下:
1 BELLMAN-FORD(G, w, s)
2 INITIALIZE-SINGLE-SOURCE(G, s)
3 for i 1 to |V[G]| - 1
4 do for each edge (u, v) E[G]
5 do RELAX(u, v, w)
6 for each edge (u, v) E[G]
7 do if d[v] > d[u] + w(u, v)
8 then return FALSE
9 return TRUE
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define DEBUG 1
#define MAXN 200 +5
#define MAXM 1000+5
int MAXINF =0x3f3f3f3f;
int G[MAXN][MAXN] ={MAXINF};
int cost_d[MAXN] = {MAXINF};
int N,M;
int S,T;
struct Edge{
int u,v,d;
}Edges[MAXM];
void init(){
memset(G,MAXINF,sizeof(G));
memset(cost_d,MAXINF,sizeof(cost_d));
S = T =-1;
memset(Edges,0,sizeof(Edges));
}
void solve(){
while(scanf("%d%d",&N,&M) == 2 ){
init();
int a,b,d;
for(int i=0;i<M;i++){
scanf("%d%d%d",&a,&b,&d);
//一定要将所有的边加入进来 无向边算两条
Edges[i].u = a,Edges[i].v = b;Edges[i].d = d;
Edges[i+M].u = b,Edges[i+M].v = a;Edges[i+M].d = d;
G[a][b] = G[b][a] = d;
}
scanf("%d%d",&S,&T);
cost_d[S] = 0;
//计算最短路径, 进行V-1次遍历
for(int i =1;i<N;i++){
for(int j=0;j<2*M;j++){
Edge& edge = Edges[j];
//即到V的距离是否可以先到U再到V,比之前COST数组里记录的距离短。
if(cost_d[edge.u] + edge.d < cost_d[edge.v]){
cost_d[edge.v] = cost_d[edge.u] + edge.d;
}
}
}
//没有负边所以不需要判定
// int flag =1 ;
// for(int i=0;i<2*M;i++){
// Edge& edge = Edges[i];
// if(cost_d[edge.v] > edge.d + cost_d[edge.u])
// flag =0;break;
// }
//
// if(flag ){
if(cost_d[T] == MAXINF){
printf("-1\n");
}else{
printf("%d\n",cost_d[T]);
}
// }
}
}
int main()
{
if(DEBUG )
freopen("data.txt","r",stdin);
solve();
return 0;
}