ABC 325

E - Our clients, please wait a moment

https://atcoder.jp/contests/abc325/tasks/abc325_e

類題: https://atcoder.jp/contests/abc395/tasks/abc395_e

社用車だけを使ったときの場合のグラフ $G$ と電車だけを使った場合のグラフ $G^\prime$ を作り、$G$ の各ノードから同じ都市に対応する $G^\prime$ のノードへコスト 0 の辺を張る。

都市 $i$ に対応する $G$ におけるノード番号を $i$, $G^\prime$ におけるノードの番号を $N + i$ とする。 求める答えはノード 1 から出発してノード $N$ またはノード $2N$ に到達するまでの最小コストである。 ($1 \rightarrow N+1$ への移動はコスト 0 でできるから出発は 1 から出発するケースだけ考えればよい)

struct Edge {
    ll to, cost;
};

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, a, b, c;
    cin >> n >> a >> b >> c;

    vvll D(n, vll(n));
    rep(i, n) rep(j, n) cin >> D[i][j];

    vector<vector<Edge>> graph(n * 2);
    rep(i, n) rep(j, n) {
        if (i == j)
            continue;
        graph[i].push_back({j, D[i][j] * a});
        graph[j].push_back({i, D[i][j] * a});
        graph[n + i].push_back({n + j, D[i][j] * b + c});
        graph[n + j].push_back({n + i, D[i][j] * b + c});
    }
    rep(i, n) graph[i].push_back({n + i, 0});

    vll dist(n * 2, INF);
    dist[0] = 0;

    // cost, pos
    using P = pair<ll, ll>;
    priority_queue<P, vector<P>, greater<P>> pq;

    pq.push({0, 0});
    while (pq.size()) {
        auto [cost, now] = pq.top();
        pq.pop();

        if (dist[now] < cost)
            continue;

        for (auto [to, cost] : graph[now]) {
            if (dist[to] <= dist[now] + cost)
                continue;

            dist[to] = dist[now] + cost;
            pq.push({dist[to], to});
        }
    }

    cout << min(dist[n - 1], dist[n * 2 - 1]) << '\n';
}