Pintia 天梯地圖 dijkstra進階

Ke_scholar發表於2024-03-31

7-14 天梯地圖 - SMU 2024 spring 天梯賽3(補題) (pintia.cn)

dijkstra進階做法,包含路徑記錄,以及按權重統計路徑條件等;

不過最開始我一直將優先佇列開的最大堆,但是一直過不了自己的例子,後來改成最小堆並且路徑值改成負數存進去就對了,再後來我發現改成最大堆也可以,不過要把點值改成負數,最後才煥然大悟,這題路徑取最短的同時,節點值也應該儘量的小(

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

struct DIJ {
    using i64 = long long;
    using PII = pair<i64, i64>;
    vector<i64> dis, path, node;
    vector<vector<array<int, 3>>> G;
    int n;

    DIJ() {}
    DIJ(int n): n(n) {
        node.resize(n + 1, 1);
        dis.assign(n + 1, 1e18);
        G.resize(n + 1);
        path.resize(n + 1, -1);
    }

    void add(int u, int v, int w, int val) {
        G[u].push_back({v, w, val});
    }

    void dijkstra(int s) {
        priority_queue<PII,vector<PII>,greater<PII>> que;
        dis[s] = 0;
        que.push({0, -s});
        while (!que.empty()) {
            auto p = que.top();
            que.pop();
            int u = -p.second;
            if (dis[u] < p.first) continue;
            for (auto [v, w, val] : G[u]) {
                if (dis[v] > dis[u] + w) {
                    node[v] = node[u] + val;
                    dis[v] = dis[u] + w;
                    que.push({ dis[v], -v});
                    path[v] = u;
                } else if (dis[v] == dis[u] + w) {
                    if (node[v] > node[u] + val) {
                        node[v] = node[u] + val;
                        path[v] = u;
                    }
                }
            }
        }
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    DIJ time(n), way(n);
    while (m --) {
        int u, v, c, t, w;
        cin >> u >> v >> c >> w >> t;
        time.add(u, v, t, w);
        way.add(u, v, w, 1);
        if (!c) {
            time.add(v, u, t, w);
            way.add(v, u, w, 1);
        }
    }

    int st, ed, ok;
    cin >> st >> ed;
    time.dijkstra(st);
    way.dijkstra(st);

    ok = ed;
    vector<int> ans, ans1;
    while (ok != -1) {
        ans.push_back(ok);
        ok = time.path[ok];
    }
    ok = ed;
    while (ok != -1) {
        ans1.push_back(ok);
        ok = way.path[ok];
    }

    if (ans1 == ans) {
        cout << "Time = " << time.dis[ed] << "; ";
        cout << "Distance = " << way.dis[ed] << ": ";
        for (int i = ans1.size() - 1; i >= 0; i --) {
            cout << ans1[i] ;
            if (i) cout << " => ";
            else cout << '\n';
        }
    } else {
        cout << "Time = " << time.dis[ed] << ": ";
        for (int i = ans.size() - 1; i >= 0; i --) {
            cout << ans[i] ;
            if (i) cout << " => ";
            else cout << '\n';
        }
        cout << "Distance = " << way.dis[ed] << ": ";
        for (int i = ans1.size() - 1; i >= 0; i --) {
            cout << ans1[i] ;
            if (i) cout << " => ";
            else cout << '\n';
        }
    }

    return 0;
}

相關文章