关于求最短路径:

求最短路径的算法有许多种,除了排序外,恐怕是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. spring中间scope详细解释

    0.思维导图 1. scope概论 spring中scope是一个很关键的概念.简单说就是对象在spring容器(IOC容器)中的生命周期,也能够理解为对象在spring容器中的创建方式. 2. sc ...

  2. UNIX网络编程卷1 server编程范式0 迭代server

    本文senlie原版的.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.迭代 TCP server总是在全然处理某个客户的请求后才转向下一个客户. 2.从进程控 ...

  3. Git & Github 一页简明笔记(转)main

    由于小组工程需要使用git&github的版本控制来协作,但我对其使用并不熟悉,特此写篇一页的笔记放在手边,备随时查阅. 使用方法:常用命令供随时查阅,其余内容供新手了解. 0. 常用命令一览 ...

  4. JavaScript之事件处理详解

    一.事件传播机制 客户端JavaScript程序(就是浏览器啦)采用了异步事件驱动编程模型.当文档.浏览器.元素或与之相关的对象发生某些有趣的事情时,Web浏览器就会产生事件(event).如果Jav ...

  5. maven 编

    Eclipse   对    run  as   [Run Configurations] main标签. Goals:输入命令:clean install -Dmaven.test.skip=tru ...

  6. ubuntu 14.04 hadoop eclipse 0配置基本环境

    动人的hadoop第二天.构造hadoop该环境还花了两天时间,在这里写自己配置的过程,我希望能帮助! 我将文中用到的全部资源都分享到了  这里,点开就能下载,不须要一个个的找啦! 当中有<Ha ...

  7. Use PRODUCT_USER_PROFILE To Limit User

    The PRODUCT_USER_PROFILE (PUP) table provides product-level security that supplements the user-level ...

  8. 挑逗B少年搞计划10 假设你是愿意用我的心脏层剥离一层~

        这些天都非常推迟考试啊.然后,学校已安排一周培训,是的.在延迟学习,大狼医院我真的是正常水平.     幸好我们周六周日不让放假了,不然预计进度直接就停了.这两天也是抽出了时间把敲了一下三层的 ...

  9. C#精华(文章3版本)笔记

    C#精华(文章3版本) 跳转至: 导航. 搜索 文件夹 1 C#概述 2 数据类型 3 运算符和控制流 4 方法和參数 5 类 6 继承 7 接口 8 值类型(struct) 9 合式类型 10 异常 ...

  10. CreateCompatibleDC工作原理

    WindowsGDI的接口没提供这种功能机制.仅仅能是先通过CreateCompatibleDC 创建一个与显示器设备内容兼容的内存设备内容.用SelectObject将位图选入内存设备内容,再用Bi ...