单源最短路问题(SSSP)常用的算法有Dijkstra,Bellman-Ford,这两个算法进行优化,就有了Dijkstra+heap、SPFA(Shortest Path Faster Algorithm)算法。这两个算法写起来非常相似。下面就从他们的算法思路、写法和适用场景上进行对比分析。如果对最短路算法不太了解,可先看一下相关ppt:最短路

为了解释得简单点,以及让对比更加明显,我就省略了部分细节。

我们先看优化前的:

\(O(V^2 + E)\)的Dijkstra

n-1次循环

-->找到未标记的d最小的点

-->标记,松弛它的边

\(O(VE)\)的Bellman-Ford

n-1次循环

-->对所有边松弛

还能再松弛则有负环

  • Dijkstra是每次确定了到一个点的最短距离,再用该点更新到其它点的距离。不能处理有负边的图。
  • Bellman-Ford是每次对所有边松弛。可以计算出有负边无负环的最短路,可以判断是否存在负环。

接下来再看优化后的:

\(O((V + E)lgV)\)的Dijkstra+heap优化

用STL中的优先队列实现堆:

while(优先队列非空)

-->队头出队,松弛它的边

-->松弛了的<新距离,点>入队

删了部分定义和初始化的代码:

typedef pair<int,int> PII;
priority_queue<PII,vector<PII>,greater<PII> > q;
...
while(!q.empty()){ // O(V) 加上count<n可以优化一点点
int w=q.top().first, u=q.top().second;
q.pop(); // O(lgV)
if(b[u])continue; b[u]=true;
//++count;
for(int i=head[u];i;i=e[i].next){ // Sum -> O(E)
int v=e[i].to;
if(d[u]+e[i].w<d[v]){
d[v]=d[u]+e[i].w;
q.push(PII(d[v],v)); // O(lgV)
}
}
}

\(O(kE)\)\(O(VE)\)的SPFA

while(队非空)

-->队头出队,松弛它的边

-->松弛了且不在队内的点入队

while(!q.empty()){
int u=q.front(); q.pop();
b[u]=false;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(d[u]+e[i].w<d[v]){
d[v]=d[u]+e[i].w;
if(!b[v])b[v]=true,q.push(v);
}
}
}

算法思路对比

  • Dijkstra+heap是用小根堆,每次取出d最小的点,来更新距离,那么这个点来说,最小距离就是当前的d。
  • SPFA是用双端队列,每次取出队头,来更新距离,它之后可能还会入队。它是一种动态逼近法,因为每次松弛距离都会减小,所以松弛一定会有结束的。如果一个点入队超过n次就是存在负环。

复杂度分析对比

Dijkstra+heap

  • 因为是堆,取队头需要O(lgV)。
  • 松弛边时,因为点的d改变了,所以点v需要以新距离重新入堆,O(lgV),总共O(ElgV)。
  • 因此总的是\(O((V + E)lgV)\)

SPFA

  • 论文证明也不严格。复杂度不太好分析。
  • 总的是O(kE)。k大概为2。
  • 复杂度应该是 \(O(VE)\)。

适用场景

如果是稠密图,Dijkstra+heap比SPFA快。稀疏图则SPFA更快。SPFA可以有SLF和LLL两种优化,SLF就是d比队头小就插入队头,否则插入队尾。

另外,Dijkstra和Prim也很相似,它们的区别主要是d的含义,前者是到s的临时最短距离,后者是到树的临时最短距离,相同点是,每次找d最小的更新其它点的距离。

【最短路算法】Dijkstra+heap和SPFA的区别的更多相关文章

  1. 10行实现最短路算法——Dijkstra

    今天是算法数据结构专题的第34篇文章,我们来继续聊聊最短路算法. 在上一篇文章当中我们讲解了bellman-ford算法和spfa算法,其中spfa算法是我个人比较常用的算法,比赛当中几乎没有用过其他 ...

  2. (转)最短路算法--Dijkstra算法

    转自:http://blog.51cto.com/ahalei/1387799         上周我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短 ...

  3. 最短路算法 Dijkstra 入门

    dijkstra算法 是一种单源点最短路算法求出一个点到其他所有点的最短路. 给你这样的一个图,需要求出1号点到其他点的最短距离是多少. 首先我们开一个数组 d[N],d[x] 代表着从起点出发到x点 ...

  4. [ACM] 最短路算法整理(bellman_ford , SPFA , floyed , dijkstra 思想,步骤及模板)

    以杭电2544题目为例 最短路 Problem Description 在每年的校赛里,全部进入决赛的同学都会获得一件非常美丽的t-shirt. 可是每当我们的工作人员把上百件的衣服从商店运回到赛场的 ...

  5. 最短路算法 —— Dijkstra算法

    用途: 解决单源最短路径问题(已固定一个起点,求它到其他所有点的最短路问题) 算法核心(广搜): (1)确定的与起点相邻的点的最短距离,再根据已确定最短距离的点更新其他与之相邻的点的最短距离. (2) ...

  6. 图的最短路算法 Dijkstra及其优化

    单源最短路径算法 时间复杂度O(N2) 优化后时间复杂度为O(MlogN)(M为图中的边数 所以对于稀疏图来说优化后更快) 不支持有负权的图 #include<iostream> usin ...

  7. 最短路算法详解(Dijkstra/SPFA/Floyd)

    新的整理版本版的地址见我新博客 http://www.hrwhisper.me/?p=1952 一.Dijkstra Dijkstra单源最短路算法,即计算从起点出发到每个点的最短路.所以Dijkst ...

  8. 最短路算法(floyed+Dijkstra+bellman-ford+SPFA)

    最短路算法简单模板 一.floyed算法 首先对于floyed算法来说就是最短路径的动态规划解法,时间复杂度为O(n^3) 适用于图中所有点与点之间的最短路径的算法,一般适用于点n较小的情况. Flo ...

  9. hdoj 2544 最短路【dijkstra or spfa】

    最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

随机推荐

  1. hdu6249 区间动态规划

    题目链接 题意:给出一些区间,求选k个区间能覆盖的最多点的数量 思路:定义dp[i][j]为前i个点取j个区间的最大值.dp[i][j]可以转移到dp[i+1][j+1]和以i+1为起点的区间终点 具 ...

  2. spring实例入门

    首先是bean文件: package onlyfun.caterpillar; public class HelloBean {    private String helloWord = " ...

  3. jmeter操作数据库

    1)     jmeter不能直接连数据库,需要先添加jar包. 然后将jar包的路径添加到下图: 2)     操作数据库之前要知道数据库的信息(ip.端口号.账号.密码),操作哪个数据库就连哪个: ...

  4. Apache Tomcat® - Which Version Do I Want?

    Apache Tomcat® - Which Version Do I Want?http://tomcat.apache.org/whichversion.html

  5. MySQL查询优化注意下面的四个细节

    原文:http://bbs.landingbj.com/t-0-244231-1.html 在任何一个数据库中,查询优化都是不可避免的一个话题.对于数据库工程师来说,优化工作是最有挑战性的工作.MyS ...

  6. Day 3-6 生成器&迭代器

    ---恢复内容开始--- 列表生成式: list = [i*i for i in range(20)] # 这就是一个列表生成式 print(list) # [0, 1, 4, 9, 16, 25, ...

  7. StringTokenizer

    StringTokenizer是一个用来分隔String的应用类,相当于VB的split函数. 1.构造函数 public StringTokenizer(String str) public Str ...

  8. python之路--MySQL 库,表的详细操作

    一 库操作 数据库命名规则 可以由数字,字母,下划线,@, #, $ 区分大小写 唯一性 不能使用关键字如 create  select 不能单独使用数字 最长128位 # 这些是对上次的补充. 二 ...

  9. Linux在shell中进入python敲方向键出现「^[[C^[[D」的解决办法

    安装yum -y install readline-devel,然后在重新编译python

  10. python数据结构与算法第十四天【二分查找】

    1.二分查找的原理 对于已经排序的列表进行最快速度的查找 2. 代码实现 (1)递归实现 def binary_search(alist, item): if len(alist) == 0: ret ...