Submission #1309837

#TimeUsernameProblemLanguageResultExecution timeMemory
1309837elt0nCommuter Pass (JOI18_commuter_pass)C++20
100 / 100
200 ms19076 KiB
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

const long long INF = 1e18;

// Функция Дейкстры для поиска кратчайших путей
void dijkstra(int start, vector<long long>& dist, int n, const vector<vector<pair<int, int>>>& adj) {
    dist.assign(n + 1, INF);
    dist[start] = 0;
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;
    pq.push({0, start});
    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();
        if (d > dist[u]) continue;
        for (auto& edge : adj[u]) {
            if (dist[u] + edge.second < dist[edge.first]) {
                dist[edge.first] = dist[u] + edge.second;
                pq.push({dist[edge.first], edge.first});
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int n, m, s, t, u, v;
    cin >> n >> m >> s >> t >> u >> v;
    vector<vector<pair<int, int>>> adj(n + 1);
    for (int i = 0; i < m; i++) {
        int a, b, c; cin >> a >> b >> c;
        adj[a].push_back({b, c});
        adj[b].push_back({a, c});
    }

    vector<long long> distS(n + 1), distT(n + 1), distU(n + 1), distV(n + 1);
    dijkstra(s, distS, n, adj);
    dijkstra(t, distT, n, adj);
    dijkstra(u, distU, n, adj);
    dijkstra(v, distV, n, adj);

    long long min_st = distS[t];
    long long ans = distU[v];

    // DP для поиска оптимальных точек входа/выхода на кратчайшем пути
    vector<long long> dpU(n + 1, INF), dpV(n + 1, INF);
    vector<int> in_degree(n + 1, 0);
    vector<vector<int>> dag(n + 1);

    for (int i = 1; i <= n; i++) {
        for (auto& edge : adj[i]) {
            // Если ребро входит в кратчайший путь S -> T
            if (distS[i] + edge.second + distT[edge.first] == min_st) {
                dag[i].push_back(edge.first);
                in_degree[edge.first]++;
            }
        }
    }

    queue<int> q;
    for (int i = 1; i <= n; i++) {
        if (in_degree[i] == 0) q.push(i);
    }

    // Топологическая сортировка и DP
    while (!q.empty()) {
        int curr = q.front(); q.pop();
        dpU[curr] = min(distU[curr], dpU[curr]);
        dpV[curr] = min(distV[curr], dpV[curr]);
        
        // Потенциально минимизируем ответ
        if (distS[curr] + distT[curr] == min_st) {
            ans = min({ans, distU[curr] + dpV[curr], distV[curr] + dpU[curr]});
        }

        for (int next : dag[curr]) {
            dpU[next] = min(dpU[next], dpU[curr]);
            dpV[next] = min(dpV[next], dpV[curr]);
            if (--in_degree[next] == 0) q.push(next);
        }
    }

    cout << ans << endl;
    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...