关于Bellman-Ford的过程

来源:9-5 负权边和Bellman-Ford算法

慕UI5584032

2018-01-26

刘老师我一直不太明白 Bellman-Ford算法最外层for循环的意思,里面for循环可以走完逻辑的,比如最简单的1->3(5),1->2(6),2->3(-2)这个图,按照您的代码

for( int i = 0 ; i < G.V() ; i ++ ){    

    (这个循环不就是遍历出三个点的全部边了嘛,然后下面逻辑判断的结果是2次松弛操作,最终得到最短路径1->2->3,另外得到最短路径后,原路径在下次循环的话还需要在继续遍历出来嘛)

            typename Graph::adjIterator adj(G,i);      

            for( Edge<Weight>* e = adj.begin() ; !adj.end() ; e = adj.next() )    

             

                if( from[e->v()] && 

                    (!from[e->w()] || distTo[e->v()] + e->wt() < distTo[e->w()]) ){    

                    distTo[e->w()] = distTo[e->v()] + e->wt();    

                    from[e->w()] = e;    

                }    

        }    


写回答

1回答

liuyubobobo

2018-01-26

首先非常抱歉,这个课程视频里我的bellman-ford代码稍微有些问题。请参考这个问答,里面有详细的说明:https://coding.imooc.com/learn/questiondetail/7968.html


总体来说,bellman-ford的外层循环的意思是:进行V-1次循环,每一次都求出从起始点,经过i步可以到达的节点的最短距离。所以,我们这层循环最多执行V-1步即可。因为我们的图一共有V个节点,从起始点到图中另一个节点,最多只需要经过V-1步。(仔细比较一下我的代码,也是为了表达这个意思,循环变量我起名为pass,是从1开始循环的)


至于你举得例子,由于很简单,没有反应出所有可能的情况。试一下这个例子:

1->3(-2)

2->1(6)

2->3(5)

起始点是2。


此时,我们在第一重循环是找不到2->1->3这个路径的,必须经过第二轮松弛操作:)希望通过这个例子你可以看出问题在哪里:我们在bellman-ford的算法中是没有控制边松弛的顺序的。我们只是每一轮按照一个固定顺序把所有的边松弛一遍而已。而你给出的例子,其实依赖于在一轮松弛操作中,先处理了1->2,又处理了2->3。这是一种特殊情况。但是为了让所有情况都没有问题,我们最多对所有边做V-1次松弛操作就好了。


当然,bellman-ford算法还可以优化,在上面我提到的问答里,包括其中的别的同学的讨论里,也提到了。有兴趣可以深入研究看:)

4
7
寒冷的高纬度
回复
liuyubobobo
看了这个解释茅舍顿开,哈哈
2020-07-11
共7条回复

算法与数据结构(C++版) 面试/评级的算法复习技能包

课程专为:短时间内应对面试、升职测评等艰巨任务打造

11187 学习 · 1614 问题

查看课程