はまやんはまやんはまやん

hamayanhamayan's blog

ワープ [第四回 アルゴリズム実技検定 J]

https://atcoder.jp/contests/past202010-open/tasks/past202010_j

前提知識

解説

https://atcoder.jp/contests/past202010-open/submissions/21472629

ダイクストラをするが、特殊なグラフ形成をする必要がある。
ダイクストラをよく知らずにこの問題を解くのは難しいので、先にダイクストラをマスターすることをお勧めする。

ワープが無ければ

普通にダイクストラするだけ。
これでまずはグラフを作る。

ワープをどうするか

真面目にワープの辺を貼ると、タイプAの全ての頂点からタイプBの全ての頂点にコストXabの辺を貼るみたいなことを
たくさんやらなきゃいけないので、明らかに数が多い。
そこで、タイプAからタイプBへの遷移を
タイプAの頂点 -0-> タイプA入まとめ集合 -Xab-> タイプB出まとめ集合 -0-> タイプBの集合
とやると任意のタイプAからタイプBへの移動を網羅的に表現できる。
これを他の全てのワープについて実装して、ダイクストラすれば答えが得られる。

int N, M, Xab, Xac, Xbc; string S;
vector<pair<int, int>> E[101010];
enum { A, B, C, A2, B2, C2 };
//---------------------------------------------------------------------------------------------------
template<typename T> using min_priority_queue = priority_queue<T, vector<T>, greater<T>>;
int vis[101010];
void dijk(int s, vector<ll>& D) {
    rep(i, 0, N + 12) D[i] = infl;
    rep(i, 0, N + 12) vis[i] = 0;

    min_priority_queue<pair<ll, int>> que;

    D[s] = 0;
    que.push({ 0, s });

    while (!que.empty()) {
        auto q = que.top(); que.pop();

        ll cst = q.first;
        int cu = q.second;

        if (vis[cu]) continue;
        vis[cu] = 1;

        fore(p, E[cu]) {
            ll cst2 = cst + p.second;
            int to = p.first;

            if (chmin(D[to], cst2)) que.push({ D[to], to });
        }
    }
}
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> N >> M >> Xab >> Xac >> Xbc >> S;
    rep(i, 0, M) {
        int a, b, c; cin >> a >> b >> c;
        a--; b--;
        E[a].push_back({ b, c });
        E[b].push_back({ a, c });
    }
    rep(i, 0, N) {
        if (S[i] == 'A') {
            E[i].push_back({ N + A, 0 });
            E[N+A2].push_back({ i, 0 });
        } else if (S[i] == 'B') {
            E[i].push_back({ N + B, 0 });
            E[N + B2].push_back({ i, 0 });
        } else if (S[i] == 'C') {
            E[i].push_back({ N + C, 0 });
            E[N + C2].push_back({ i, 0 });
        }
    }

    E[N + A].push_back({ N + B2, Xab });
    E[N + A].push_back({ N + C2, Xac });
    E[N + B].push_back({ N + A2, Xab });
    E[N + B].push_back({ N + C2, Xbc });
    E[N + C].push_back({ N + A2, Xac });
    E[N + C].push_back({ N + B2, Xbc });

    vector<ll> dst(N + 12);
    dijk(0, dst);
    cout << dst[N - 1] << endl;
}