【最短路算法】Dijkstra+heap和SPFA的区别

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

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

我们先看优化前的:

O(V2+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最小的更新其它点的距离。

posted @   水郁  阅读(12130)  评论(4编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
欢迎这位怪蜀黍来到《【最短路算法】Dijkstra+heap和SPFA的区别 - 水郁 - 博客园》
点击右上角即可分享
微信分享提示