http://www.cnblogs.com/mengxm-lincf/archive/2012/02/11/2346288.html
其实我一直存在疑惑是什么导致dijkstra不能处理负权图?
今日偶见某大牛说一句“dijkstra选定一个节点后节点值不在改变”,方才大悟。
本质上就是dijkstra选点方式导致的(即贪心),只针对目前的情况作出最好的判断
1)在非负权图中这点是没有错的
2)在负权图中就出错了,如
0 2 4
2 0 -3
4 -3 0
为什么呢?
证明dijkstra可行的最重要定理:即当i被选中时,dist(i)=min{w(s->i)}
定理证明:若不存在一个节点j可以松弛i,那么显然定理成立,否则必存在某一节点j,dist(i)>w(j,i)+dist(j),那么由于在非负权图中所以w(j,i)>0,则dist(i)>dist(j),那么在选择i之前j一定已经被选走,由此推出矛盾,定理证毕。由定理可知贪心在此的正确性。
看到前面证明中关键点(红字处),如果在负权图中那么w(j,i)>0就不一定成立,则定理也就不成立了,贪心也必然是错误的。
再看bellman-ford,假设图G存在最短路径a->b->c->d
循环松弛:第一次找到a->b
第二次找到a->b->c
第三次找到a->b->c->d
但是注意图G至少存在1条最短路,第几次循环松弛就是同时确定所有最短路的第几个节点(注意是第几个节点而不是具体的哪一个点),也就是说在bellman-ford的操作中无法再某一时刻确定某一个节点的dist是最短路径值,但是可以确定当n-1循环松弛后所有最短路一定确定了,因为图G最长的最短路其边数一定小于等于n-1,所以从一条最短路的角度看n-1次松弛后最短路径一定确定了。
再看bellman-ford的负权回路检验,dist(i)>dist(j)+w(j,i)。
为什么这个式子成立即有负权回路。显然若是不存在负权回路那么根据最短路的性质上式不可能成立,因为经过n-1循环松弛所有最短路都已确定那么dist是原点到个点的最短距离,根据最短路的最优子结构,dist(i)<=dist(j)+w(j,i)。
简证:
显然若dist(j)不是最后一轮松弛才出现,则在下一轮松弛中会使dist(i)更新,那么就不会出现上式,那也就是说i必须在以j为终点的最短路中,s->i->j,如果没有i,则dist(j)不可能在最后一轮松弛中才出现,现在可以发现有一个循环i->j,j->i,且这个循环使j的值不断减小,那么这个循环只能是负权的,证毕。
注意dist(i)>dist(j)+w(j,i)可行前提条件是dist是最短路径,由于dijkstra在负权图的无法得出正确最短路径所以无法使用该使检查是否存在负权回路。
floyd可以检查回路(无论正负)
但是floyd的负权检查可以简单一点,即dist[i][i]<INF,判断i终值是否小于初始值,因为若存在负权回路那么必有至少一个点其值在n次循环松弛后由于负权回路的原因小于其初始值。注意这种简化检验只适合于问题:原点不确定的图中是否存在负权回路。同理dist[i][i]>INF,判断i终值是否大于初始值,判断正权回路。