最短路之保存最短路径

模板题:4196. 最短路径 - AcWing题库

思路:设置一个pre数组保存该节点的前驱节点,每一次更新路径都更新一下该节点的前驱节点,最后递归输出最短路。

细节:有数据范围:1≤m≤1e5,1≤w≤1e6可得,最长路径为1e11,所以需要使用LL
因为LL是八个字节,所以INF=0x3f3f3f3f3f3f3f3fll,注意最后有个ll

解法1:spfa(优先考虑)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef long long LL;

const int N = 100010, M = 200010, INF = 0x3f3f3f3f3f3f3f3fll;

int h[N], e[M], w[M], ne[M], idx;
int n, m, pre[N], pp;
LL dist[N];
bool st[N];

void add(int a, int b, int c)
{
    w[idx] = c;
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

int spfa()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    queue<int> q;
    q.push(1);
    st[1] = true;
    
    while(q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        
        for(int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                pre[j] = t;    //被更新
                if(!st[j]) 
                {
                    st[j] = true;
                    q.push(j);
                }
            }
        }
    }
    
    return dist[n];
    
}

void out(int x)
{
    if(pre[x] == -1)
    {
        cout << x;
        return ;
    }
    out(pre[x]);
    cout << " " << x;
    return ;
}

int main()
{
    memset(h, -1, sizeof h);
    memset(pre, -1, sizeof pre);
    
    cin >> n >> m;
    for(int i = 0; i < m; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
        add(b, a, c);
    }
    
    LL t = spfa();
    
    if(t == INF) cout << -1 << endl;
    else    out(n);
    
    return 0;
    
}

解法2:dijkstra

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef long long LL;

typedef pair<LL, int> PII;

const int N = 100010, M = 200010;
const LL INF = 0x3f3f3f3f3f3f3f3fll;

int n, m, pre[N];
int h[N], e[M], ne[M], w[M], idx;
bool st[N];
LL dist[N];

void add(int a, int b, int c)
{
    w[idx] = c;
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

int heap_djikstra()
{
    memset(dist, 0x3f, sizeof dist);    
    priority_queue<PII, vector<PII>, greater<PII> > heap;
    
    heap.push({0, 1});
    dist[1] = 0;
    while(heap.size())
    {
        auto t = heap.top();
        heap.pop();
        
        int ver = t.second;
        LL distance = t.first;
        if(st[ver]) continue;
        st[ver] = true;
        
        for(int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(dist[j] > distance + w[i])
            {
                pre[j] = ver;    //被更新
                dist[j] = distance + w[i];
                heap.push({dist[j], j});
            }
        }
    }
    
    if(dist[n] == INF)  return -1;
    return 0;
}

void out(int x) //递归输出最短路径,行尾无空格
{
    if(pre[x] == -1)
    {
        cout << x;
        return ;
    }
    out(pre[x]);
    cout << " " << x;
    return ;
}

int main()
{
    memset(h, -1, sizeof h);
    memset(pre, -1, sizeof pre);
    
    cin >> n >> m;
    while (m -- )
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);   add(b, a, c);   //无向图
    }
    
    int t = heap_djikstra();
    if(t == -1)    puts("-1");
    else    out(n);
    
    
    return 0;
}


应用:

posted @ 2022-05-05 08:41  光風霽月  阅读(22)  评论(0编辑  收藏  举报