Submission #443068

#TimeUsernameProblemLanguageResultExecution timeMemory
443068arujbansalCommuter Pass (JOI18_commuter_pass)C++17
100 / 100
417 ms25340 KiB
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <array>
#include <stack>
#include <queue>
#include <random>
#include <numeric>
#include <functional>
#include <chrono>
#include <utility>
#include <iomanip>
#include <assert.h>

using namespace std;

void dbg_out() { cerr << endl; }
template<typename Head, typename... Tail>
void dbg_out(Head H, Tail... T) { cerr << ' ' << H; dbg_out(T...); }
#define dbg(...) cerr << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)

#define rng_init mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define rng_seed(x) mt19937 rng(x)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int) (x).size()
#define int long long

template<typename T>
struct Dijkstra {
    const T INF = numeric_limits<T>::max();

    struct state {
        int u;
        T dist;

        state() {}

        state(int _u, T _dist) : u(_u), dist(_dist) {}

        bool operator<(const state &other) const {
            return dist > other.dist;
        }
    };

    int n;
    vector<vector<pair<int, T>>> graph;
    vector<T> dist;
    vector<int> parent;

    Dijkstra(int _n = 0) {
        init(_n);
    }

    void init(int _n) {
        n = _n;
        graph.resize(n);
    }

    void add_directional_edge(int u, int v, T weight) {
        graph[u].emplace_back(v, weight);
    }

    void add_bidirectional_edge(int u, int v, T weight) {
        add_directional_edge(u, v, weight);
        add_directional_edge(v, u, weight);
    }

    void run(const vector<int> &source) {
        priority_queue<state> pq;
        dist.assign(n, INF);
        parent.assign(n, -1);

        for (const auto &u : source) {
            dist[u] = 0;
            parent[u] = u;

            pq.emplace(u, 0);
        }

        while (!pq.empty()) {
            auto [u, cur_dist] = pq.top();
            pq.pop();

            if (dist[u] != cur_dist) continue;

            for (const auto &[v, weight] : graph[u]) {
                T new_dist = cur_dist + weight;

                if (new_dist < dist[v]) {
                    dist[v] = new_dist;
                    parent[v] = u;
                    pq.emplace(v, new_dist);
                }
            }
        }
    }

    bool reachable(int u) {
        return dist[u] < INF;
    }
};

const int MXN = 1e5 + 5, INF = 1e18;

void solve() {
    int N, M, S, T, U, V;
    cin >> N >> M >> S >> T >> U >> V;

    Dijkstra<int> solver(N + 1);

    while (M--) {
        int u, v, wt;
        cin >> u >> v >> wt;

        solver.add_bidirectional_edge(u, v, wt);
    }

    solver.run(vector<int>{U});
    vector<int> u_dist = solver.dist;

    int ans = u_dist[V];

    solver.run(vector<int>{V});
    vector<int> v_dist = solver.dist;

    solver.run(vector<int>{S});
    vector<int> s_dist = solver.dist;

    solver.run(vector<int>{T});
    vector<int> t_dist = solver.dist;

    vector<pair<int, int>> dag_order;
    for (int i = 1; i < sz(s_dist); i++)
        dag_order.emplace_back(s_dist[i], i);

    sort(all(dag_order));

    vector<int> dp1(N + 1, INF), dp2(N + 1, INF);

    for (const auto &[cur_dist, node] : dag_order) {
        dp1[node] = u_dist[node];
        dp2[node] = v_dist[node];

        for (const auto &[v, wt] : solver.graph[node]) {
            if (s_dist[v] > s_dist[node]) continue;

            if (s_dist[v] + wt + t_dist[node] == s_dist[T]) {
                ans = min({ans, dp1[v] + v_dist[node], dp2[v] + u_dist[node]});

                dp1[node] = min(dp1[node], dp1[v]);
                dp2[node] = min(dp2[node], dp2[v]);
            }
        }
    }

    cout << ans;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int TC = 1;
    // cin >> TC;
    while (TC--) solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...