中级篇——Bellmen算法求最短路径

来源:互联网 发布:黑马java 2016 编辑:程序博客网 时间:2024/06/16 17:37

        Bellmen算法是求最短路径的最方便的算法之一,SPFA算法更方便,是Bellmen算法的队列实现但队列不会,掌握Bellmen算法即可解决大部分最短路径的问题。Bellmen算法的最大优势就在于可以解决边权值为负的情况。(限于有向图)

        另外,Bellmen算法的运算时间为O(nm)适合n^2>m的稀疏图!!!当遇到n^2<m的稠密图时最好用Dijkstra算法,其运算时间为O(n^2)。

典例:给n个点,m条路径,求A点到B点的最短路径。

需要开设dis[]记录,dis[i]即到达i点的最短距离,输出时输出dis[i]即可。

*核心代码:

for(int i=1;i<=n-1;i++)        {            for(int j=1;j<=m;j++)            {                if(dis[edge[j].v]>dis[edge[j].u]+edge[j].w)                    dis[edge[j].v]=dis[edge[j].u]+edge[j].w;            }        }

理论上一共要进行n-1轮松弛,但有可能最后几轮的松弛将不再改变dis[]中的值,故可以提前结束循环节省运算时间。需要一个与dis[]一样大的数组dis1[]备份dis[]的值,另外还引进一个flag变量初始化为0。每次松弛过后将dis[]与dis1[]中的值一一比对,若相同则flag=1;判断if(flag==1)则结束循环无需再松弛。

#include <iostream>#include<stdio.h>#define max 99999999using namespace std;int dis[200],dis1[200],n,m,a,b;struct node{    int u,v,w;       //起点。重点,权值}edge[100];void init()          //初始化{    for(int i=1;i<=n;i++)        dis[i]=max;  //初始化将到达每个点的距离设为无穷    dis[a]=0;      //起点开始故距离为0}int main(){    while(cin>>n>>m>>a>>b)    {        init();        for(int i=1;i<=m;i++)        {            cin>>edge[i].u>>edge[i].v>>edge[i].w;        }        //bellmen核心语句!!!        int flag;        for(int i=1;i<=n-1;i++)        {            flag=0;              for(int j=1;j<=m;j++)            {                if(dis[edge[j].v]>dis[edge[j].u]+edge[j].w)                    dis[edge[j].v]=dis[edge[j].u]+edge[j].w;            }    for(int j=1;j<=n;j++)            if(dis[j]!=dis1[j])                {                                 flag=1;dis1[j]=dis[j];                }             if(flag==0) break;   //若值均未变则跳出循环        }        //输出结果        cout<<dis[b]<<endl;    }    return 0;}


数据:

Input:5   5   1   5

             2   3   2

             1   2   -3

             1   5   5

             4   5   2

             3   4   3

Output:4

运算过程(理解运算原理)

初始化:dis     1           2            3          4          5

                           0       max       max     max     max

第一轮:先处理第一条边,2——>3距离为2,此时dis[2]和dis[3]均为max,无法比较,松弛失败。第二条边1——>2距离为-3,此时dis[1]=0,dis[2]=max,dis[2]>dis[1]+(-3),故dis[2]值变为-3。第三条边1——>5距离为5,dis[5]>dis[1]+5,故dis[5]=5。以此方法,第三四条边无法松弛,故第一轮松弛结束。

                dis     1           2            3          4          5

                           0         -3         max      max       5

第二轮:处理刚才未松弛成功的第一条边2——>3,dis[3]>dis[2]+(-3),dis[3]=-1。之后3——>4,dis[4]>dis[3]+3,dis[4]=2。发现了从4——5距离会比1——>5短,但松弛3——>4时已经过了4——>5的边,只能再进行一轮松弛。

                dis     1           2            3          4          5

                           0         -3            -1         2          5

第三轮:处理4——>5,dis[5]>dis[4]+2,dis[5]=4。

                dis     1           2            3          4          5

                           0         -3            -1         2          4

第四轮:无变化的值,flag=0,跳出循环。

                dis     1           2            3          4          5

                           0         -3            -1         2          4





0 0
原创粉丝点击