原理:是对图进行V-1次松弛操作,得到所有可能的最短路径。其优于迪科斯彻算法的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达。但算法可以进行若干种优化,提高了效率。
自然语言描述:
对有向图,用贝尔曼-福特算法求以为源点的最短路径的过程:
- 建立,表示目前已知源点到各个节点的最短距离,起始值 ,其余皆为。
- 建立,表示某节点路径上的父节点,起始值皆为NULL。
- 对,比较和,并将小的赋给,如果修改了则(松弛操作)
- 重复以上操作次
- 再重复操作一次,如,则此图存在负权环。
-
-
松弛:每次松弛操作实际上是对相邻节点的访问,第次松弛操作保证了所有深度为n的路径最短。由于图的最短路径最长不会经过超过条边,所以可知贝尔曼-福特算法所得为最短路径。
-
负边权操作:与迪科斯彻算法不同的是,迪科斯彻算法的基本操作“拓展”是在深度上寻路,而“松弛”操作则是在广度上寻路,这就确定了贝尔曼-福特算法可以对负边进行操作而不会影响结果。
-
负权环判定:因为负权环可以无限制的降低总花费,所以如果发现第次操作仍可降低花销,就一定存在负权环。
-
-
贝尔曼福特代码(真)//绝对不是网上随便搜的伪代码!
bool SP_Bellman(int s)
{
memset(dis,10,sizeof(dis));
dis[s]=0;
for(int i=1;i<=n;i++)
{
rel=false;
for(int j=1;j<=m*2+w;j++)
if(dis[a[j].xx]+a[j].vv<dis[a[j].yy])
{
dis[a[j].yy]=a[j].vv+dis[a[j].xx];
rel=true;
}
if (!rel) return 0;
}
return 1;
}