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);
}

猜你喜欢

转载自www.cnblogs.com/liuwenyao/p/11185224.html
今日推荐