zoukankan      html  css  js  c++  java
  • 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
    ", 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);
    }
    
  • 相关阅读:
    网易云服务器使用https
    网站搬家后firefox,chrome提示内容编码错误,360浏览器提示500错误
    腾讯云centos服务器配置
    微擎二次开发相关
    mysql 分组查询最新的/最高的一条记录
    .htaccess ci放在子目录时规则
    小程序 html解析
    源于一道文字游戏的题目
    C# 获取系统时间及时间格式
    操作bin目录下的文件
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11185224.html
Copyright © 2011-2022 走看看