Submission #1340111

#TimeUsernameProblemLanguageResultExecution timeMemory
1340111miraclemagicianCommuter Pass (JOI18_commuter_pass)C++20
100 / 100
277 ms19444 KiB
#include <iostream>
#include <vector>
#include <queue>
#include <numeric>
#include <algorithm>

using namespace std;
using ll = long long;
const ll INF = 1e18;

int main() {
    // Fast I/O
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int N, M;
    if (!(cin >> N >> M)) return 0;

    int S, T, U, V;
    cin >> S >> T >> U >> V;

    vector<vector<pair<int, ll>>> adj(N + 1);
    for (int i = 0; i < M; i++) {
        int u, v;
        ll w;
        cin >> u >> v >> w;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    // 1. Lambda for Dijkstra - cleanly captures 'adj' and 'N' from the outer scope
    auto run_dijkstra = [&](int start, vector<ll>& dist) {
        dist.assign(N + 1, INF);
        dist[start] = 0;
        
        // Min-heap for Dijkstra
        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;
        pq.push({0, start});

        while (!pq.empty()) {
            auto [d, u] = pq.top(); // Structured binding
            pq.pop();

            if (d > dist[u]) continue;

            for (const auto& [v, w] : adj[u]) {
                if (dist[u] + w < dist[v]) {
                    dist[v] = dist[u] + w;
                    pq.push({dist[v], v});
                }
            }
        }
    };

    // 2. Run the 4 Dijkstras
    vector<ll> distS, distT, distU, distV;
    run_dijkstra(S, distS);
    run_dijkstra(T, distT);
    run_dijkstra(U, distU);
    run_dijkstra(V, distV);

    // 3. Topological sort nodes based on their distance from S
    vector<int> order(N);
    iota(order.begin(), order.end(), 1);
    
    // Lambda for custom sorting
    sort(order.begin(), order.end(), [&](int a, int b) {
        return distS[a] < distS[b];
    });

    // 4. DP arrays initialized to the base distances
    vector<ll> dpU = distU;
    vector<ll> dpV = distV;
    
    // Initial answer: cost without using the commuter pass at all
    ll ans = distU[V]; 

    // 5. Traverse the DAG and calculate the answer
    for (int u : order) {
        for (const auto& [v, w] : adj[u]) {
            // Check if edge u -> v is on ANY shortest path from S to T
            if (distS[u] + w + distT[v] == distS[T]) {
                // Push the minimum distances from U and V down the DAG
                dpU[v] = min(dpU[v], dpU[u]);
                dpV[v] = min(dpV[v], dpV[u]);
            }
        }
    }

    // 6. Evaluate all valid exit points on the S -> T shortest paths
    for (int i = 1; i <= N; ++i) {
        if (distS[i] + distT[i] == distS[T]) {
            ans = min(ans, dpU[i] + distV[i]); // S -> T direction overlap
            ans = min(ans, dpV[i] + distU[i]); // T -> S direction overlap
        }
    }

    cout << ans << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...