最短路径算法----Bellman-ford和SPFA算法
来源:互联网 发布:卸载预装软件 编辑:程序博客网 时间:2024/06/06 01:12
核心也是:对于边e(i,j), 如果w(i) + e(i,j) < w(j),就更新w(j)。这是一个松弛操作,即:估计的最短路径值渐渐地被更加准确的值替代,直至得到最优解(wiki)
对于图
有
def bellman_ford(graph, start_node):# graph:n*n matrix# find min distance from start_nodelength = len(graph)s = {start_node:0} # the minimum distance between node i and v# init s: O(Vertex)for node in xrange(0, length):if node == start_node:continues[node] = max_int# loose# run (vertex - 1) timesfor v in xrange(1, length):# for every edgefor i in xrange(0, length):for j in xrange(0, length):if graph[i][j] != max_int and s[i] + graph[i][j] < s[j]:s[j] = s[i] + graph[i][j]return s
使用二维矩阵表示图,时间复杂度是O(Vertex^3);
如果使用图数据结构,可以达到O(Vertex * Edge)
由于存在负权回路,还有一步检查的操作:def test_negate_circle(graph, s):# for every edgelength = len(graph)for i in xrange(0, length):for j in xrange(0, length):if graph[i][j] != max_int and s[i] + graph[i][j] < s[j]:return Truereturn False
如果有负值回路,就说明永远能找到到目标点更小的一条边。
对于上面的第一张图,深度为1,显然只需要遍历一次边就能得到结果了。但是对于第二张图,在最坏的情况下,需要遍历3次才可以。
下面假设所有边的权值为1,人肉模拟一下最坏结果:
第一遍:u:{0:0, 1:1, 2:max_int, 3:max_int}
第二遍:u:{0:0, 1:1, 2:2, 3:max_int}
第三遍:u:{0:0, 1:1, 2:2, 3:3}
所以,遍历Vertex-1次可以改为:遍历所有边的最大深度。
什么是遍历所有边的最大深度?
从上图来看,如果用BFS遍历所有点得到图的深度为2:
第零层:0
第一层:1,2
第二层:3
但是实际上,可能存在0->1->2->3,使得0~3的距离最短。
遍历所有边的最大深度的结果则是:
第零层:0
第一层:1[e(0,1)],2[e(0,2)]
第二层:2[e(1,2)]
第三层:3[e(2,3)]
这个层数只是估算出来的最坏情况,也就是循环次数的上界
实际上,如果在一次遍历所有的边的时候,没有松弛操作,那么继续遍历也没有意义了。
这就是SPFA的思想:松弛操作必定只会发生在最短路径前导节点松弛成功过的节点上,用一个队列记录松弛过的节点,可以避免了冗余计算。
也就是说,只有对更新过的w(i),才有可能出现w(i) + e(i,j) < w(j)。第一个更新的就是开始节点啦,更新后的权重为0。
def SPFA(graph, start_node):length = len(graph)s = {i:max_int for i in xrange(0, length)}s[start_node] = 0queue_loose = deque([start_node])circle_tester = defaultdict(lambda : 0)while queue_loose:i = queue_loose.popleft()# update sfor j in xrange(0, length):if graph[i][j] != max_int and s[i] + graph[i][j] < s[j]:s[j] = s[i] + graph[i][j]queue_loose.append(j)# test circlecircle_tester[j] += 1if circle_tester[j] == length:# has negate circlereturn Nonereturn s
负权环的检测我也写在SPFA里面了,如果一个节点访问次数大于Vertex次,就认为有环。
原因我猜想是:最多有Vextex-1个节点(除去自己)会对某个节点产生影响,如果大于这个数,说明有负环。
如果不对,希望大家提出指正~谢谢
驱动
graph = [[0, 7, 9, max_int, max_int, 14], [7, 0, 10, 15, max_int, max_int], [9, 10, 0, 11, max_int, 2], [max_int, 15, 11, 0, 6, max_int], [max_int, max_int, max_int, 6, 0, 9], [14, max_int, 2, max_int, 9, 0]]print SPFA(graph, 0)
- 最短路径算法----Bellman-ford和SPFA算法
- 【最短路径】:Dijkstra算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法
- *最短路径 Bellman-Ford & SPFA 算法实战
- 单点最短路径算法 bellman-ford模板和队列优化后的spfa算法模板
- 最短路径算法---Bellman-Ford
- 最短路径Bellman-Ford算法
- 【算法】最短路径之Bellman-Ford
- 最短路径bellman-ford算法模板
- Bellman Ford 最短路径算法
- Bellman-Ford算法【最短路径】
- Bellman ford 最短路径算法
- BellMan-Ford算法--寻找最短路径
- 【图】最短路径Bellman-Ford算法
- 最短路径(Bellman-Ford算法)
- 最短路径算法—Bellman-Ford
- Bellman-Ford最短路径算法
- 最短路径问题--Bellman-Ford最短路径算法
- (最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法模板的整理与介绍
- LeetCode | 28. Implement strStr()——寻找子串
- java_web环境部署
- Linux图形界面当中,将调整屏幕大小的解决办法。
- c#中queue队列用法
- ofstream和ifstream详细用法
- 最短路径算法----Bellman-ford和SPFA算法
- 离散题目10
- uva 12096The SetStack Computer
- CSS里的浏览器前缀
- TCP socket编程实现
- Vue.js学习之路—使用vue-cli搭建项目
- 排序算法总结(11)--总结
- express手册之二,快速搭建
- ubuntu下chmod命令的用法