SPFA算法 学习。

来源:互联网 发布:原野发胶淘宝假货 编辑:程序博客网 时间:2024/06/06 02:00

SPFA算法:求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm,是Bellman-Ford算法0(VE)的一个优化,期望的时间复杂度O(2E),E为图的边数,所以SPFA用在稀疏图上的效果会更加明显。SPFABellman-Ford算法优化的关键之处在于意识到:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变

很多时候,给定的图存在负权边,这时类似Dijkstra算法(0(V^2),在稠密图上有优势)便没有了用武之地,而bellman_ford的复杂度又过高,SPFA算法便派上用场了。


算法核心思想:理解这个算法,最好先看看Bellman-Ford,因为他是对Bellman-Ford的一个优化,SPFA算法采用了一个队列,优化算法,用数组dict[]记录每个结点的最短路径估计值,而且用邻接表来存储图G。我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。

需要注意的是:仅当图不存在负权回路时,SPFA能正常工作。如果图存在负权回路,由于负权回路上的顶点无法收敛,总有顶点在入队和出队往返,队列无法为空,这种情况下SPFA无法正常结束。

1 记录每个结点进队次数,超过|V|次表示有负权
2 记录这个结点在路径中处于的位置,ord[i],每次更新的时候ord[i]=ord[x]+1,若超过|V|则表示有负圈....

下面举一个实例来说明SFFA算法是怎样进行的:

设有一个有向图G{VE},其中,V={V0,V1,V2,V3,V4}E ={<V0,V1>,<V0,V4>,<V1,V2>,<V1,V4>,<V2,V3>,<V3,V4>,<V4,V2>} ={2,10,3,7,4,5,6},见下图:  

    

算法执行时各步的Queue队的值和D数组的值由下表所示:

                   

算法执行到第五步后,队Queue空,算法结束。源点V0V1的最短路径为2,到V2的最短路径为5,到V3的最短路径为9,到V4的最短路径为9,结果显然是正确的。

学习了。

附上一道练习题,传送门。

原创粉丝点击