【原创】求最短路径-Bellman-Ford算法

Bellman-Ford算法

事先吐槽:几十年前的坑了!赶紧填完赶紧轻松

引子

有这样一类题,它要求你从某个点出发,到某个为止走过的最短路径。很早很早以前,我们学习了弗洛伊德算法迪杰斯塔拉算法
现在我们再来看看与前两种完全不同的做法。

算法原理与流程

Bellman-Ford算法的流程如下:
在图G(V, E)(V为点集,E为边集),取一源点s,数组Dis[i]记录从源点s到顶点i的路径长度,初始化Dis全清∞,Dis[s]为0;
以下操作循环执行至多n-1次,n为顶点数:
对于每一条边e(u, v),如果Dis[u] + w(u, v) < Dis[v],则令Dis[v] = Dis[u]+w(u, v)。w(u, v)为边e(u,v)的权值;
如果对Dis[n]没有被更新,说明最短路径已经查找完毕,或者图不连通,则跳出循环。否则执行下次循环。

简单来讲,就是不停的枚举边,看能不能枚举出一条最短路径。

检测负环路

如果图中存在负环路,dijk会不停打转,Floyd理都不会理,那么Bellman-Ford呢?
为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Dis[u] + w(u, v) < Dis[v]的边,则图中存在负环路,即是说该图无法求出单源最短路径。否则数组Dis[n]中记录的就是源点s到各顶点的最短路径长度。

时间复杂度

由上,Bellman-Ford算法的时间复杂度为O(V*E),适合于稀疏图

代码实现

#include<iostream> 
#include<cstdio> 
using namespace std;  

#define MAX 0x7fffffff
#define N 1010 
int nodenum, edgenum, original; //点,边,起点 

struct Edge //边 
{  
    int u, v;  
    int cost;  
}Edge;  

Edge edge[N];  
int dis[N], pre[N];  

bool Bellman_Ford()  
{  
    for(int i = 1; i <= nodenum; ++i) //初始化 
        dis[i] = (i == original ? 0 : MAX);  
    for(int i = 1; i <= nodenum - 1; ++i)  
        for(int j = 1; j <= edgenum; ++j)  
        {
            if(dis[edge[j].v] > dis[edge[j].u] + edge[j].cost) //松弛
            {  
                dis[edge[j].v] = dis[edge[j].u] + edge[j].cost;  
                pre[edge[j].v] = edge[j].u;  
            }  
        }

        bool flag = 1; //判断是否含有负权回路 
        for(int i = 1; i <= edgenum; ++i)  
            if(dis[edge[i].v] > dis[edge[i].u] + edge[i].cost)  
            {  
                flag = 0;  
                break;  
            }  
        return flag;
}  

void print_path(int root) //打印最短路的路径(反向) 
{  
    while(root != pre[root]) //前驱 
    {  
        printf("%d-->", root);  
        root = pre[root];  
    }  
    if(root == pre[root])  
        printf("%d\n", root);  
}  

int main()  
{  
    scanf("%d%d%d", &nodenum, &edgenum, &original);  
    pre[original] = original;  
    for(int i = 1; i <= edgenum; ++i)  
    {  
        scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost);  
    }  
    if(Bellman_Ford())  
        for(int i = 1; i <= nodenum; ++i) //每个点最短路 
        {  
            printf("%d\n", dis[i]);  
            printf("Path:");  
            print_path(i);  
        }  
    else  
        printf("have negative circle\n");  
    return 0;  
}  

代码转自:http://blog.csdn.net/niushuai666/article/details/6791765

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