最短路问题之Bellman-Ford算法

我们来说一下图论的最短路问题

这一部分主要有三种做法:Bellman-Ford算法、Dijkstra算法、Floyd-Warshall算法


我们先来看Ford:

Ford和Dijkstra一样,都是考虑单元最短路问题,我们用一个图来理解一下最短路的思想:

现在我们给这些边赋上权值,我们要找到从左到右的最短路,假设每条边的权值都是1,那么我们能直观地得出它的最短路,是最下面的一条,但是计算机可没有我们这么好用的大脑,我们用计算机的运行方式来模拟一遍:

我们要从左到右找最短路,以左端点为起点,向上走,接着走上方的边,走到右端点回溯,得到的路径长度是4;

重新以左端点为起点,向上走,转向向下的边,接着走下方的边,走到右端点回溯,得到的路径长度是4;

重新以左端点为起点,向下走,接着走下方的边,走到右端点回溯,得到的路径长度是4;

比较三段路径长度,得到最短路是3。

懂得了计算最短路的方法以后,我们开始看ford算法的精髓:

        记从起点S出发到顶点i的最短距离为d[i],则下列等式成立。

        d[i]=min{d[j]+(i到j的权值)|e=(j,i)∈E}

        即,d[i]=min(d[i],d[j]+e,cst[j]);

如果给定的图是一个DAG,就可以按拓扑序给顶点编号,并利用这条递推关系式计算出d。但是,如果图中有环,就无法依赖这样的顺序进行计算。在这种情况下,记当前到顶点i的最短路长度为d[i],并设处置d[s]=0,d[i]=INF,在再断使用这条递推关系式更新d的值,就可以计算出新的d。只要图中不存在负环,这样的更新操作就是有限的,也就是说,这种更新操作一定是有终点的。结束之后的d就是所求的最短距离了。

struct edge{int frm,to,cst;}es[MAXN];
int d[MAXN];
int v,e;
void Bellman-Ford(int s){
    for(int i=0;i<v;i++) d[i]=INF;
    d[s]=0;//起点到本身的最短路为0
    while(true){
        bool updt=false;
        for(int i=0;i<e;i++){
            edge eg=es[i];
               if(d[eg.frm]!=INF && d[eg.to]>d[eg.frm]+eg.cst){
                    d[eg.to]=d[eg.frm]+eg.cst;
                    updt=true;
               }
        }
        if(!updt) break;
    }
}

看懂了这段代码,我们就可以考虑刚才说过的一个概念:对d[i]的更新操作,终点是什么?

根据这段代码的原理我们可以看出,如果在图中不存在从S可达的负环,那么最短路不会经过一个顶点两次,也就是说,while循环最多执行|V|-1次,即最短路最多经过|V|-1条边。如果存在从S可达的负环,那么在第|V|次操作中也会更新d的值,因此,可以用这个性质来检验图中是否存在负环。如果一开始对于所有的顶点i,都把d[i]初始化城0,那么可以检查出图中所有的负环。

bool find_nagtive_loop(){
    memset(d,0,sizeof(d));
    for(int i=0;i<=v;i++) for(int j=0;j<e;j++){
        edge eg=es[j];
        if(d[eg.to]>d[eg.frm]+eg.cst){d[eg.to]=d[eg.frm]+eg.cst;if(i==v-1) return true;}
        //如果第n次更新了d的值,则存在负环
    }
    return false;
}

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 

(人造分隔线)

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oblivion_Zzz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值