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);
    }
    
  • 相关阅读:
    Maximum Flow Exhaustion of Paths Algorithm
    ubuntu下安装java环境
    visualbox使用(二)
    vxworks一个超级奇怪的错误(parse error before `char')
    February 4th, 2018 Week 6th Sunday
    February 3rd, 2018 Week 5th Saturday
    February 2nd, 2018 Week 5th Friday
    February 1st, 2018 Week 5th Thursday
    January 31st, 2018 Week 05th Wednesday
    January 30th, 2018 Week 05th Tuesday
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11185224.html
Copyright © 2011-2022 走看看