关于求最短路径:

求最短路径的算法有许多种,除了排序外,恐怕是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|次,那么就可以断定图中存在负权回路了。

参考资料:

百度百科: SPFA  、 dijstra算法

博客:http://blog.csdn.net/kg_second/article/details/7894298

www.cnblogs.com/zgmf_x20a/archive/2008/12/18/1357737.html

求最短路径算法之SPAF算法。的更多相关文章

  1. 求最短路径的三种算法: Ford, Dijkstra和Floyd

    Bellman-Ford算法 Bellman-Ford是一种容易理解的单源最短路径算法, Bellman-Ford算法需要两个数组进行辅助: dis[i]: 存储顶点i到源点已知最短路径 path[i ...

  2. JS实现最短路径之弗洛伊德(Floyd)算法

    弗洛伊德算法是实现最小生成树的一个很精妙的算法,也是求所有顶点至所有顶点的最短路径问题的不二之选.时间复杂度为O(n3),n为顶点数. 精妙之处在于:一个二重初始化,加一个三重循环权值修正,完成了所有 ...

  3. C++迪杰斯特拉算法求最短路径

    一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...

  4. 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径

    自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...

  5. Dijkstra算法求最短路径(java)(转)

    原文链接:Dijkstra算法求最短路径(java) 任务描述:在一个无向图中,获取起始节点到所有其他节点的最短路径描述 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到 ...

  6. js迪杰斯特拉算法求最短路径

    1.后台生成矩阵 名词解释和下图参考:https://blog.csdn.net/csdnxcn/article/details/80057574 double[,] arr = new double ...

  7. 最短路径算法之四——SPFA算法

    SPAF算法 求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm,该算法是西南交通大学段凡丁于1994年发表的. 它可以在O(kE)的时间复杂度内求出源点 ...

  8. 最短路径算法之Dijkstra算法(java实现)

    前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是“贪心算法”的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知 ...

  9. 图中最短路径算法(Dijkstra算法)(转)

    1.Dijkstra 1)      适用条件&范围: a)   单源最短路径(从源点s到其它所有顶点v); b)   有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E ...

随机推荐

  1. GDI+学习笔记(六)渐变画笔

    刷,顾名思义,它是一样的刷.提请设备,还记得常唱歌曲,"我是一个画家.." 好吧.跑题了. 本系列博客希望尽可能简单的描写叙述每项功能,而不希望把每一个參数都介绍的详具体细,假设须 ...

  2. 使用php+swoole对client数据实时更新(二) (转)

    上一篇提到了swoole的基本使用,现在通过几行基本的语句来实现比较复杂的逻辑操作: 先说一下业务场景.我们目前的大多数应用都是以服务端+接口+客户端的方式去协调工作的,这样的好处在于不论是处在何种终 ...

  3. 在Mac OS上配置Android开发环境

    1)安装配置NDK 1.1 下载NDK并解压缩 下载路径 https://developer.android.com/tools/sdk/ndk/index.html 在terminal运行: chm ...

  4. Swift: 打造滑动解锁文字动画

    原文:Swift: 打造滑动解锁文字动画 最近木事,找出来玩了玩facebook的paper.到处都是那个"slide to unlock your phone"的效果啊.忽闪忽闪 ...

  5. zoj 3829 Known Notation(2014在牡丹江区域赛k称号)

    Known Notation Time Limit: 2 Seconds      Memory Limit: 131072 KB Do you know reverse Polish notatio ...

  6. Ohloh研究报告

    1.底       由于近期接合ospaf同样是一个开源项目的成熟度分析工具,由于该项目现在Ohloh我们有共同的东西,这么ohloh我们进行了调查.       简单的说,初始ohloh是一个代码搜 ...

  7. unity3d 学习笔记_____Native2d 刚体、冲击、联合使用

    Mass Mass of the rigidbody. Linear Drag Drag coefficient affecting positional movement. Angular Drag ...

  8. Oracle 树操作

    Oracle 树操作(select…start with…connect by…prior) oracle树查询的最重要的就是select…start with…connect by…prior语法了 ...

  9. Appium在手机浏览器使用滑屏Not yet implemented解决办法。

    在手机浏览器使用swipe.scroll等手机特有行为时,因为默认context是WEBVIEW,所有一定要切换回NATIVE_APP才可以使用. python: driver.switch_to.c ...

  10. 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 ...