제출 #1154525

#제출 시각아이디문제언어결과실행 시간메모리
115452554skyxenonCommuter Pass (JOI18_commuter_pass)C++17
100 / 100
457 ms40972 KiB

// https://oj.uz/problem/view/JOI18_commuter_pass

#include <bits/stdc++.h>
using namespace std;

#define int int64_t
#define INF INT64_MAX

int32_t main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    int s, t;
    cin >> s >> t;
    s--;
    t--;

    int u, v;
    cin >> u >> v;
    u--;
    v--;

    vector<set<pair<int, int>>> graph(n);
    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        a--;
        b--;
        graph[a].insert({b, c});
        graph[b].insert({a, c});
    }

    auto dijkstra = [&](int source) -> vector<int> {
        vector<int> dist(n, INF);
        dist[source] = 0;

        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
        pq.push({0, source});

        while (pq.size()) {
            auto [curr_d, curr] = pq.top();
            pq.pop();

            if (curr_d > dist[curr]) {
                continue;
            }

            for (auto& [nei, cost] : graph[curr]) {
                int new_cost = cost + curr_d;
                if (new_cost < dist[nei]) {
                    pq.push({new_cost, nei});
                    dist[nei] = new_cost;
                }
            }
        }

        return dist;
    };

    vector<int> dist_u = dijkstra(u);
    vector<int> dist_v = dijkstra(v);

    // Modified Dijkstra with state (best, min penalty including u + v from that best)
    vector<pair<int, int>> dist(n, {INF, INF});
    priority_queue<tuple<int, int, int, int, int>, vector<tuple<int, int, int, int, int>>, greater<tuple<int, int, int, int, int>>> pq;
    pq.push({0, dist_u[s] + dist_v[s], dist_u[s], dist_v[s], s});

    while (pq.size()) {
        auto [d, total_penalty, u_penalty, v_penalty, curr] = pq.top();
        pq.pop();

        if (pair<int, int>{d, total_penalty} > dist[curr]) {
            continue;
        }

        // printf("Looking at node %d with cost %d and penalty %d so far!\n", curr, curr_d, curr_penalty);
        for (auto& [nei, cost] : graph[curr]) {
            int new_cost = cost + d;
            int new_u_penalty = min(u_penalty, dist_u[nei]);
            int new_v_penalty = min(v_penalty, dist_v[nei]);
            int new_total_penalty = min(total_penalty, new_u_penalty + new_v_penalty);
            if (pair<int, int>{new_cost, new_total_penalty} < dist[nei]) {
                pq.push({new_cost, new_total_penalty, new_u_penalty, new_v_penalty, nei});
                dist[nei] = {new_cost, new_total_penalty};
            }
        }
    }

    cout << min(dist[t].second, dist_u[v]) << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...