Official

H - Roads and Gates Editorial by en_translator


By creating sur-vertices \(W _ S\) and \(W _ T\) and allowing travel from vertex \(i\) to \(W _ S\) in \(X _ i\) minutes, from \(W _ S\) to \(W _ T\) in \(Y\) minutes, and from \(W _ T\) to \(j\) in \(X _ j\) minutes, the problem is reduced to a single-source shortest path problem on a graph with \((N+2)\) vertices and \((2N+M+1)\) edges.

This can be solved with an algorithm like Dijkstra’s algorithm.

The following is sample code.

#include <iostream>
#include <vector>
#include <queue>
#include <ranges>

int main() {
    using namespace std;
    unsigned N, M, Y;
    cin >> N >> M >> Y;

    vector<vector<pair<unsigned, unsigned>>> edges(N + 2);
    for (unsigned i{}; i < M; ++i) {
        unsigned u, v, T;
        cin >> u >> v >> T;
        edges[--u].emplace_back(--v, T);
        edges[v].emplace_back(u, T);
    }

    for (unsigned i{}; i < N; ++i) {
        unsigned X;
        cin >> X;
        edges[i].emplace_back(N, X); // From each vertex to W_S
        edges[N + 1].emplace_back(i, X); // From W_T to each vertex
    }
    
    edges[N].emplace_back(N + 1, Y); // from W_S to W_T

    // Use Dijkstra's algorithm to find a shortest path
    vector<unsigned> distance(N + 2, 3000000000);
    priority_queue<pair<unsigned, unsigned>, vector<pair<unsigned, unsigned>>, greater<>> pq;
    pq.emplace(distance[0] = 0, 0);
    while (!empty(pq)) {
        const auto [dist, now]{pq.top()};
        pq.pop();
        if (distance[now] < dist) continue;

        for (const auto& [next, cost] : edges[now])
            if (distance[next] > dist + cost)
                pq.emplace(distance[next] = dist + cost, next);
    }

    for (const auto d : distance | views::take(N) | views::drop(1))
        cout << d << " ";
    cout << endl;
    return 0;
}