SPFA最短路算法解析
2016-02-15 19:36
246 查看
SPFA是一个比较高效的算法,虽说在比较大的数据时仍然无法比Dijkestra+Heap快,但是代码却很简单,以我的水平而言,代码要短上一倍以上。SPFA这个算法的实用性比较强,所以在OI中是一个相当不错的算法。 SPFA是Bellman-Ford算法的常数优化,如果再加上LLL优化和SLF优化,就更加强大了。下面,我们来剖析其本质:【SPFA的定义】 SPFA的定义和Bellman-Ford的很像,首先,Bellman-Ford的定义是每一轮都对于每一个点进行所谓的“松弛”操作,用另一种方法来讲就是用能够到达当前点的最短路来更新所有的临近点。而SPFA的优化,则是注意到了不一定要对每一个点进行这样的操作,而只需要对于更新了的点。也就是说,SPFA的算法描述大概是这样的:首先将除了起点外到其他所有点的最短路径全部设为INF,即无穷大,然后将起点放入队列,每一次只对队列的头元素进行“松弛”操作,然后将该操作所能够更新到的点全部插入队列尾部,并将队列头元素弹出。而这,就是SPFA。 其实SPFA的真实情况比这还要简单,根据杨鸿飞所说的那样,这SPFA就是一个能够将一个点多次入队的广搜!想想看,这个广搜,不就是每一次将能够更新的点加入队列吗?或者说这也是一种迭代,每一次不断地更新那些能够更新的点,并将新的能够更新的点继续更新,直到完全无法更新为止,或者说,就是上面的那个“广搜”的队列完全为空为止。
【SPFA的框架】 既然都说了SPFA是一个最短路径算法,那应用的前景也很广泛了。但是,有一点要注意:SPFA很可能要使用循环队列!因为SPFA中的点会多次入队,很难估计实际所会使用的队列大小,所以应该在有一定空间赋予的情况下,使用循环队列,避免出现“假溢出”之类的问题。 SPFA的框架很简单,如果不考虑循环队列的话,就是这样:
【SPFA的框架】 既然都说了SPFA是一个最短路径算法,那应用的前景也很广泛了。但是,有一点要注意:SPFA很可能要使用循环队列!因为SPFA中的点会多次入队,很难估计实际所会使用的队列大小,所以应该在有一定空间赋予的情况下,使用循环队列,避免出现“假溢出”之类的问题。 SPFA的框架很简单,如果不考虑循环队列的话,就是这样:
1.将所有点到起点的最短距离全部置为无穷大 2.将起点到自己的距离设为0 3.将起点放入队列中 4.用当前队列的头结点去更新其的邻近的节点 5.将能够更新的节点入队列 6.弹出当前队列的头结点,如果队列为空,跳到7,否则跳到4 7.最后将相应的最短路径输出至于循环队列,也同样简单。 我觉得最简单的方法,也最不容易出错的方法,是先写一个不用循环队列的SPFA,然后再将所有的关于访问队列数组的地方,全部在下标后面模一下队列数组的大小即可。虽说模运算比较慢,但是这样不容易写错,而且一开始没有用循环队列的时候还易于调试。
相关文章推荐
- NOIP复赛的一些注意事项
- FloodFill算法的优化
- 洛谷11月月赛总结
- Dijkestra算法的理解与相应的优化
- 10.24南海NOIP模拟测解题报告
- Sparse Table算法 - RMQ问题的简单高效算法
- POJ 2342 Anniversary Party题解 - 树形DP入门题目
- IPEOI1 1-4题解题报告
- 一条sql语句分别统计出来两张表的数据
- Maze
- Tour-Guide解题报告 - 哈密尔顿环问题
- 位运算除法 - frisbee
- 比萨(Pizza)解题报告 - 暴力枚举加位运算加速
- 细菌(disease)解题报告 - 搜索与回朔
- A-B Problem(Dec)解题报告 - 单调队列
- 哈希 - O(1)的摊销复杂度 - 搜索与哈希(上)
- 题目题解简单收集
- Escape解题报告 - 提前计算对于程序的帮助 - 贪心算法与动态规划
- 2015-8-7 ACM 模拟赛制测试总结
- 来自洛谷八月月赛的一道数学问题 - 子串和 - 组合数学