ABC463E - Roads and Gates

考え方

基本的なDijkstra法の問題に、ワープが加わっただけ。

都市 $i$ から都市 $j$ へワープするコストは $X_i+X_j+Y$ かかる。
これは、以下のように解釈することができる。

すると、以下の $2$ つの超頂点を追加することで、これは素直に扱えるようになる。

ここが解決したら、あとはDijkstra法を行うだけで解ける。
辺の数が $M+2N+1$ 本あるので、計算量は $O((N+M) \log (N+M))$。

入力例1での動作

入力を受け取り、都市番号を 0-indexed に直す。

n: 7
m: 7
y: 3
u: {0, 0, 1, 2, 2, 3, 3}
v: {1, 2, 2, 4, 6, 4, 6}
w: {1, 6, 4, 8, 4, 2, 9}
x: {3, 1, 4, 1, 5, 9, 2}

都市 $0$ から都市 $6$ に加えて、超頂点を $2$ つ用意する。

隣接リストは、「重み、行き先頂点」の形で持つ。

まず、通常の道路を隣接リストに追加する。
道路は双方向なので、両向きの辺を追加する。

次に、各都市 $i$ について、都市 $i$ から超頂点 $7$ へ重み x.at(i) の辺を張る。
また、超頂点 $8$ から都市 $i$ へ重み x.at(i) の辺を張る。
最後に、超頂点 $7$ から超頂点 $8$ へ重み $y$ の辺を張る。

超頂点を含めた隣接リストは次のようになる。

graph[0]: {(1,1), (6,2), (3,7)}
graph[1]: {(1,0), (4,2), (1,7)}
graph[2]: {(6,0), (4,1), (8,4), (4,6), (4,7)}
graph[3]: {(2,4), (9,6), (1,7)}
graph[4]: {(8,2), (2,3), (5,7)}
graph[5]: {(9,7)}
graph[6]: {(4,2), (9,3), (2,7)}
graph[7]: {(3,8)}
graph[8]: {(3,0), (1,1), (4,2), (1,3), (5,4), (9,5), (2,6)}

都市 $0$ からDijkstra法を実行し、最短距離を求める。

result: {0, 1, 5, 6, 8, 14, 7, 2, 5}

答えとして、都市 $1$ から都市 $6$ までの、都市 $0$ からの最短距離 1 5 6 8 14 7 を出力する。

入力例1のグラフ
灰色の辺は通常の道路。
青い部分はワープ経路(一部、赤で色が上書きされている)。
赤い部分はDijkstra法で求めた各都市への最短経路。
$7$→$8$ は実際はこの向きの有向辺。
頂点 $7$ へ向かう辺は、$7$→$8$ を除き、実際は $7$ への有向辺。
頂点 $8$ から出る辺は、$7$→$8$ を除き、実際は $8$ からの有向辺。

注意点

最短距離は、$10^9$ 級の値をいくつも足すので、int 型からはみ出る。
long long 型を用いること。

別解

超頂点を $1$ つで解く方法もある。
ワープ装置へ行くのに $X_i+Y$、ワープ装置から帰るのに $X_i$ とすればよい。

さらに、有向辺と無向辺が入り混じることを嫌うなら、コストを全て $2$ 倍にする方法もある。
都市間の経路のコストは全て $2$ 倍、ワープ装置との行き来は $2X_i+Y$ とする。
こうすると、全て無向辺で扱うことができる。
$2X_i+Y$ が int 型に収まらなくなったり、最後に半分にする必要があったりする代償はあるが。