最短路学习+

Dijkstra 求单源最短路径,无法处理代负权的边。时间复杂度O(n^2)

http://www.wutianqi.com/?p=1890

Bellman_Ford 求单源最短路径,可以检查是否存在负权的环。时间复杂度O(v*e)

http://www.wutianqi.com/?p=1912

Spfa 求单源最短路径,是中国人发明的哦。。 同bellman可以检代负权的环,时间复杂度O(k*e)

http://www.wutianqi.com/?p=2285

floyd 求任意两地的最短路径,时间复杂度O(n^3)

http://www.wutianqi.com/?p=1903

Bellman-Ford算法思想
Bellman-Ford算法基于动态规划,反复用已有的边来更新最短距
Bellman-Ford算法的核心思想——松弛
Dist[u]和Dist[v]应当满足一个关系,即
Dist[v]<=Dist[u]+w[u,v]
反复的利用上式对Dist数组进行松弛,如果没有负权回路的话,应当会在有限次松弛之后结束。那么上限是多少次呢?
考虑对每条边进行1次松弛的时候,得到的实际上是至多经过0个点的最短路径,对每条边进行两次松弛的时候得到的是至多经过1个点的最短路径,……
果没有负权回路,那么任意两点间的最短路径至多经过n-2个点,因此经过n-1次松弛操作后应当可以得到最短路径
果有负权回路,么第n次松弛操作仍然会成功,这时,最短路径为-∞
Bellman-Ford算法流程
所有点i赋初值Dist[i]= +∞ ,出发点为s,Dist[s]=0
for k=1 to n-1
  for 每条边(u,v)
     如果d[u]!= +∞ 且d[v]>d[u]+w[u,v]  
 则d[v]=d[u]+w[u,v]
for 每条边(u,v) 
如果d[u]!= +∞ 且d[v]>d[u]+w[u,v]
 则存在负权回路
时间复杂度
法复杂度为O(VE)其中V=顶点数,E=边数
们知道Dijkstra的算法复杂度是O(V^2),经过优化的Dijkstra算法可以达到O((V+E)logE)
所以Bellman-Ford算法并不比它快,但实际上Bellman-Ford算法也是可以优化的
Bellman-Ford算法的优化
在没有回路的时候,至多进行n-1次松弛操作会得到解,但实际上可能不到n-1此松弛操作就得到最优解了
可以在每一轮松弛的时候判断是否松弛成功,如果所有的边都没有松弛的话,说明Bellman-Ford算法已经可以结束了
进一步的优化——SPFA算法
SPFA=Shortest Path Faster Algorithm
也即Bellman-Ford算法的队列优化,这里的队列可以用双向队列,也可以两个普通队列
初始时将源加入队列。每次从队列中取出一个元素,并对所有与他相邻的点进行松弛,若某个相邻的点松弛成功,则将其入队。直到队列为空时算法结束。
SPFA算法的效率
时间复杂度一般认为是O(kE)
其中k是一个较大的常数,不好估计,但是可以看出SPFA算法效率应当是很高的
经验表明Dijkstra算法的堆优化要比SPFA快,但SPFA比普通的Dijkstra算法快。而SPFA算法可以处理负权的问题,而且比Dijkstra算法的堆优化的代码要容易实现,因此SPFA是一个很好的算法

你可能感兴趣的:(最短路)