求最短路径算法之SPAF算法。
关于求最短路径:
求最短路径的算法有许多种,除了排序外,恐怕是OI界中解决同一类问题算法最多的了。最熟悉的无疑是Dijkstra(不能求又负权边的图),接着是Bellman-Ford,它们都可以求出由一个源点向其他各点的最短路径;如果我们想要求出每一对顶点之间的最短路径的话,还可以用Floyd-Warshall。
关于松弛:
松弛操作的原理是著名的定理:“三角形两边之和大于第三边”,在信息学中我们叫它三角不等式。所谓对i,j进行松弛,就是判定是否d[j]>d[i]+w[i,j],如果该式成立则将d[j]减小到d[i]+w[i,j],否则不动。
SPFA简介:
求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm,该算法是西南交通大学段凡丁于1994年发表的(一看到这点就觉得西南交大碉堡了)。它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,其中k为所有顶点进队的平均次数,可以证明k一般小于等于2,可以处理负边,但无法处理带负环的图(负环和负边不是一个概念)。SPFA的实现甚至比Dijkstra或者Bellman_Ford还要简单。
SPFA算法过程:
我们记源点为S,由源点到达点i的“当前最短路径”为D[i],开始时将所有D[i]初始化为无穷大,D[S]则初始化为0。算法所要做的,就是在运行过程中,不断尝试减小D[]数组的元素,最终将其中每一个元素减小到实际的最短路径。
过程中,我们要维护一个队列,开始时将源点置于队首,然后反复进行这样的操作,直到队列为空:
(1)从队首取出一个结点u,扫描所有由u结点可以一步到达的结点,具体的扫描过程,随存储方式的不同而不同;
(2)一旦发现有这样一个结点,记为v,满足D[v] > D[u] + w(u, v),则将D[v]的值减小,减小到和D[u] + w(u, v)相等。其中,w(u, v)为图中的边u-v的长度,由于u-v必相邻,所以这个长度一定已知(不然我们得到的也不叫一个完整的图);这种操作叫做松弛。
(3)上一步中,我们认为我们“改进了”结点v的最短路径,结点v的当前路径长度D[v]相比于以前减小了一些,于是,与v相连的一些结点的路径长度可能会相应地减小。注意,是可能,而不是一定。但即使如此,我们仍然要将v加入到队列中等待处理,以保证这些结点的路径值在算法结束时被降至最优。
判断有无负环:
如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)
SPFA算法过程图解:
如下图求从源点a到其他点的最短路径:
1、首先建立起始点a到其余各点的最短路径表格,将源点元素(a)入队列:
2、源点元素(a)出队,对以a为起始点的所有边的终点依次进行松弛操作(此处有b,c,d三个点),此时路径表格状态为:
注意这里b,c,d都使d[]数组的值变小了,且不在queue队列中,所有入队。
3、队首元素b点出队,对以b为起始点的所有边的终点依次进行松弛操作(此处只有e点),此时路径表格状态为:
4、队首元素c点出队,对以c为起始点的所有边的终点依次进行松弛操作(此处有e,f两个点),此时路径表格状态为:
注意此时e在队列中,所以e不用再次入队列形成 d e f e这种队列形式,如这样会增加冗余运算。
5、队首元素d点出队,对以d为起始点的所有边的终点依次进行松弛操作(此处只有g这个点),此时路径表格状态为:
6、队首元素e点出队,对以e为起始点的所有边的终点依次进行松弛操作(此处有g这个点),因为d[e]+map[e][g](e到g点的距离)>d[g],故g不进队列,再说g本来就在队列里面了-,-此时队列的状态:
7、队首元素f点出队,对以f为起始点的所有边的终点依次进行松弛操作(此处有d,e,g三个点),此时路径表格状态为:
d点使路径表d[d]的值变大了,不如队列; e,f的最短路径估值变小了,e在队列中存在,f不存在。因此e不用入队了,f要入队。
8、队首元素g点出队,对以g为起始点的所有边的终点依次进行松弛操作(此处只有b点),此时路径表格状态为:
9、队首元素e点出队,对以e为起始点的所有边的终点依次进行松弛操作(此处只有g这个点),此时路径表格状态为:
d[e]+map[e][g]>d[g],故g不入队列
10、队首元素b点出队,对以b为起始点的所有边的终点依次进行松弛操作(此处只有e这个点),此时路径表格状态为:
当队列为空了,即计算出了从源点带所有点的最短距离, 由上表知:
a到b的最短路径是17;
关于算法能否结束?
由上面的演示我们知道,当queue为空的时候,我们就得出结果了。那是否存在queue不为空的时候呢,答案是肯定的。
对于不存在负权回路的图来说,上述算法是一定会结束的。因为算法在反复优化各个最短路径长度,总有一个时刻会进入“无法再优化”的局面,此时一旦队列读空,算法就结束了。然而,如果图中存在一条权值为负的回路,就糟糕了,算法会在其上反复运行(因为d[]加上一个负数肯定变下了,所以在有负环的情况下,会不断有数进入队列),通过“绕圈”来无休止地试图减小某些相关点的最短路径值。假如我们不能保证图中没有负权回路,一种“结束条件”是必要的。这种结束条件是什么呢?
思考Bellman-Ford算法,它是如何结束的?显然,最朴素的Bellman-Ford算法不管循环过程中发生了什么,一概要循环|V|-1遍才肯结束。凭直觉我们可以感到,SPFA算法“更聪明一些”,就是说我们可以猜测,假如在SPFA中,一个点进入队列——或者说一个点被处理——超过了|V|次,那么就可以断定图中存在负权回路了。
参考资料:
博客:http://blog.csdn.net/kg_second/article/details/7894298
www.cnblogs.com/zgmf_x20a/archive/2008/12/18/1357737.html
求最短路径算法之SPAF算法。的更多相关文章
- 求最短路径的三种算法: Ford, Dijkstra和Floyd
Bellman-Ford算法 Bellman-Ford是一种容易理解的单源最短路径算法, Bellman-Ford算法需要两个数组进行辅助: dis[i]: 存储顶点i到源点已知最短路径 path[i ...
- JS实现最短路径之弗洛伊德(Floyd)算法
弗洛伊德算法是实现最小生成树的一个很精妙的算法,也是求所有顶点至所有顶点的最短路径问题的不二之选.时间复杂度为O(n3),n为顶点数. 精妙之处在于:一个二重初始化,加一个三重循环权值修正,完成了所有 ...
- C++迪杰斯特拉算法求最短路径
一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...
- 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径
自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...
- Dijkstra算法求最短路径(java)(转)
原文链接:Dijkstra算法求最短路径(java) 任务描述:在一个无向图中,获取起始节点到所有其他节点的最短路径描述 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到 ...
- js迪杰斯特拉算法求最短路径
1.后台生成矩阵 名词解释和下图参考:https://blog.csdn.net/csdnxcn/article/details/80057574 double[,] arr = new double ...
- 最短路径算法之四——SPFA算法
SPAF算法 求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm,该算法是西南交通大学段凡丁于1994年发表的. 它可以在O(kE)的时间复杂度内求出源点 ...
- 最短路径算法之Dijkstra算法(java实现)
前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是“贪心算法”的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知 ...
- 图中最短路径算法(Dijkstra算法)(转)
1.Dijkstra 1) 适用条件&范围: a) 单源最短路径(从源点s到其它所有顶点v); b) 有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E ...
随机推荐
- GDI+学习笔记(六)渐变画笔
刷,顾名思义,它是一样的刷.提请设备,还记得常唱歌曲,"我是一个画家.." 好吧.跑题了. 本系列博客希望尽可能简单的描写叙述每项功能,而不希望把每一个參数都介绍的详具体细,假设须 ...
- 使用php+swoole对client数据实时更新(二) (转)
上一篇提到了swoole的基本使用,现在通过几行基本的语句来实现比较复杂的逻辑操作: 先说一下业务场景.我们目前的大多数应用都是以服务端+接口+客户端的方式去协调工作的,这样的好处在于不论是处在何种终 ...
- 在Mac OS上配置Android开发环境
1)安装配置NDK 1.1 下载NDK并解压缩 下载路径 https://developer.android.com/tools/sdk/ndk/index.html 在terminal运行: chm ...
- Swift: 打造滑动解锁文字动画
原文:Swift: 打造滑动解锁文字动画 最近木事,找出来玩了玩facebook的paper.到处都是那个"slide to unlock your phone"的效果啊.忽闪忽闪 ...
- zoj 3829 Known Notation(2014在牡丹江区域赛k称号)
Known Notation Time Limit: 2 Seconds Memory Limit: 131072 KB Do you know reverse Polish notatio ...
- Ohloh研究报告
1.底 由于近期接合ospaf同样是一个开源项目的成熟度分析工具,由于该项目现在Ohloh我们有共同的东西,这么ohloh我们进行了调查. 简单的说,初始ohloh是一个代码搜 ...
- unity3d 学习笔记_____Native2d 刚体、冲击、联合使用
Mass Mass of the rigidbody. Linear Drag Drag coefficient affecting positional movement. Angular Drag ...
- Oracle 树操作
Oracle 树操作(select…start with…connect by…prior) oracle树查询的最重要的就是select…start with…connect by…prior语法了 ...
- Appium在手机浏览器使用滑屏Not yet implemented解决办法。
在手机浏览器使用swipe.scroll等手机特有行为时,因为默认context是WEBVIEW,所有一定要切换回NATIVE_APP才可以使用. python: driver.switch_to.c ...
- RPC和RMI的区别(Difference Between RPC and RMI)
RPC和RMI的区别(Difference Between RPC and RMI) RPC vs RMI RPC (Remote Procedure Call) and RMI (Remote Me ...