DIJ的优化,和spfa的优化

Posted liuwenyao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DIJ的优化,和spfa的优化相关的知识,希望对你有一定的参考价值。

SPFA和DIJ求最短路的算法的坑点一直是很多的。经常会让人搞不懂。

易错案例:

用重载运算符来排序,如:

struct cmp 
    bool operator ()(int x, int y)
    const
    
        return dis[x]>dis[y];
    
;

这种做法是不对的,该dis值在堆里不会更新甚至会堵住。

正确案例:

目前只有两种优化算法最可靠,分别为优先队列来优化spfa或dij。

\(SPFA\):

每次从堆中只需要取出到t的最短路最小的元素进行松弛,这样便可以大大缩小松弛的次数,效率从而得到提高。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#define int long long
using namespace std;
int n, m, s, a, b, vis[1000100], dis[1000100], cnt, lin[1000100];
struct cym 
    int from, to, len, nex;
e[2000100];
struct cmp
    bool operator () (int x, int y)
    
        return dis[x] > dis[y];
    
;
inline void add(int u, int v, int l)

    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].len = l;
    e[cnt].nex = lin[u];
    lin[u] = cnt;

priority_queue <int, vector <int>, cmp> q;
signed main()

    scanf("%lld%lld%lld", &n, &m, &s);
    for (int i = 1; i <= n; i++)
        dis[i] = 2147483647;
    for (int i = 1; i <= m; i++)
    
        int a, b, c;
        scanf("%lld%lld%lld", &a, &b, &c);
        add(a, b, c);
    
    dis[s] = 0;
    q.push(s);
//  printf("%d\n", lin[s]);
    while(!q.empty())
    
        int cur = q.top();
        q.pop();
        vis[cur] = 0;
        for (int i = lin[cur]; i; i = e[i].nex)
        
            if (dis[e[i].to] > dis[cur] + e[i].len)
            
                dis[e[i].to] = dis[cur] + e[i].len;
                if (!vis[e[i].to])
                
                    q.push(e[i].to);
                    vis[e[i].to] = 1;
                
            
        
    
    for (int i = 1; i <= n; i++)
        printf("%lld ", dis[i]);

\(DIJ\):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int n, m, s, lin[100010], cnt, a, b, c, vis[100010];
struct cym 
    int d, num;

dis[100100];
struct edge 
    int to, len, nex;
e[200010];
inline void add(int f, int t, int l)

    e[++cnt].len = l; e[cnt].to = t; e[cnt].nex = lin[f]; lin[f] = cnt;
   
bool operator < (cym a, cym b)

    return a.d > b.d;

priority_queue <cym> q;
int main()

    scanf("%d%d%d", &n, &m, &s);
    for (int i = 1; i <= m; i++)
    
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    
    for (int i = 1; i <= n; i++)
        dis[i].d = 2147483647, dis[i].num = i;
    dis[s].d = 0;
    q.push(dis[s]);
    while(!q.empty())
    
        cym cur = q.top(); q.pop();
        if (vis[cur.num])
            continue; 
        vis[cur.num] = 1;
        for (int i = lin[cur.num]; i; i = e[i].nex)
            if (cur.d + e[i].len < dis[e[i].to].d && !vis[e[i].to])
                dis[e[i].to].d = e[i].len + cur.d, q.push(dis[e[i].to]);
    
    for (int i = 1; i <= n; i++)
        printf("%d ", dis[i].d);

以上是关于DIJ的优化,和spfa的优化的主要内容,如果未能解决你的问题,请参考以下文章

SPFA和Dijkstra分别适用于什么方面呢?

[usaco2009febgold]道路翻新 最短路+dp

dij与prim算法

知识点汇总

图论_FatherChristmasFlymouse(Tarjan+dijkstra or spfa)

最短路-dij