Bellman-Ford算法的详解

在学习这个算法之前,相信大家都已经学习过dijkstra算法了,如果大家还看过别的关于bellman-ford算法的文章,那些文章一定讲过dijkstra算法无法解决存在负权环的图的单源最短路问题。那么我们先来看看为什么dijkstra算法不行

 

           《Bellman-Ford算法的详解》

如果我们采用dijkstra算法来求这个图的单源最短路径

经过四次松弛之后,我们认为最短路已经求出来了,其实不然。注意到图中存在2,3结点这个负权环,其实3结点的dis可以无限的的减小。而采用bellman-ford算法,对于存在负权环的图该算法可以”检测”出来。

下面我们开始讲解bellman-ford算法

这个算法的大致思想是

1,.初始化:将除源点外的所有顶点的最短距离估计值 dis[v] =+∞, dis[s] =0;
2.迭代求解:反复对边集E中的每条边进行
松弛操作
,使得顶点集V中的每个顶点v的最短距离估计值逐步逼近其最短距离;(运行|v|-1次)为什么是|v|-1次?当然嘛,一条最短路径经过的点最多是|v|-1个嘛,所有松弛|v|-1次后最短路必然会出现!
3.检验负权回路:判断边集E中的每一条边的两个端点是否收敛。如果存在未收敛的顶点,(比如说上图2-3那条边,经过|v|-1次松弛操作之后,3结点的最短距离还可以继续减小)则算法返回false,表明问题无解;否则算法返回true,并且从源点可达的顶点v的最短距离保存在 dis[v]中。

下面贴一下代码

#include <iostream>
using namespace std;
const int MAX = 1001;
const int INF = 0x3fffffff;
struct
{
     int u,v,dis;
}edge[MAX];
int dis[MAX];
int root[MAX];
bool bellman_ford(int nodenum,int start,int edgenum)
{
    for(int i=1;i<=nodenum;i++)
          dis[i] = INF;
    dis[start] = 0;
    for(int i=1;i<nodenum;i++)//如果不存在负权环,则在nodenum-1次循环后最短路必求出来
    {
          for(int j=1;j<=edgenum;j++)//松弛每一条边
          {
             if(dis[edge[j].v]>dis[edge[j].u]+edge[j].dis)
             {
                  dis[edge[j].v] = dis[edge[j].u]+edge[j].dis;
                  root[edge[j].v] = edge[j].u;
             }
          }
    }
     bool flag = true;
     for(int j=1;j<=edgenum;j++) //检查有无负权环
     {
          if(dis[edge[j].v]>dis[edge[j].u]+edge[j].dis)
          {
               flag = false;
               break;
          }
     }
     return flag;
}

 

    

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/runninghui/article/details/8886937
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞