Bellman-Ford算法的详解

来源:互联网 发布:淘宝手机端gif图 编辑:程序博客网 时间:2024/05/21 10:16

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

 

          

如果我们采用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;}






 

    

原创粉丝点击