読者です 読者をやめる 読者になる 読者になる

AOJ 0623 Zombie Island

解法

危険な街を列挙さえすれば,あとはただの単一始点最短路問題.
危険な街を列挙するには,ゾンビに支配された街を全て,最初にqueueにプッシュしておくだけで十分である.

計算量は O(N + MlogN)

ソースコード

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

using ll = long long;
using pll = pair<ll, ll>;

constexpr ll INF = 1e18;

int main() {
    int N, M, K, S;
    ll P, Q;
    cin >> N >> M >> K >> S;
    cin >> P >> Q;

    vector<ll> zd(N, INF);
    queue<int> que1;
    for(int i=0; i<K; ++i) {
        int c;
        cin >> c;
        c--;
        que1.push(c);
        zd[c] = 0;
    }

    vector<vector<int>> g(N);
    for(int i=0; i<M; ++i) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    while(!que1.empty()) {
        int v = que1.front();
        que1.pop();
        for(auto to : g[v]) {
            if(zd[to] == INF) {
                zd[to] = zd[v] + 1;
                que1.push(to);
            }
        }
    }

    vector<ll> d(N, INF);
    d[0] = 0;
    priority_queue<pll, vector<pll>, greater<pll>> que;
    que.push(make_pair(0, 0));
    while(!que.empty()) {
        pll p = que.top();
        que.pop();
        int v = p.second;
        if(d[v] < p.first) {
            continue;
        }
        for(auto to : g[v]) {
            if(zd[to] == 0) {
                continue;
            }
            ll cost = to == N-1 ? 0 : (zd[to] > S ? P : Q);
            if(d[to] > d[v] + cost) {
                d[to] = d[v] + cost;
                que.push(make_pair(d[to], to));
            }
        }
    }
    cout << d[N-1] << endl;
}