目次

AtCoder Beginner Contest 245 G問題メモ

AtCoder Beginner Contest 245

今年度も終わりだね

G - Foreign Friends

G - Foreign Friends

問題

解法

Dijkstraを基本として、2種類のカスタマイズを行う。

複数始点Dijkstra

普通、Dijkstraといえば「単一始点」の最短経路探索アルゴリズムだが、

という場合、最初にキューに突っ込む始点を複数個にしても問題ない。

この問題では、$L$ 個の特別な頂点を始点とし、全頂点への最短距離を求めればよい。

上位k番目までを求める

単なる複数始点Dijkstraで最短距離を求めても、実は始点と終点の値が同じだった!ということがあり得る。

そこで「始点に書かれた値」でグループ化して、上位2グループまでの最短距離を求めれば、 どちらかのグループは終点の値と異なるので、正しい答えとして採用できる。

●特別な頂点、○普通の頂点

❶---1---③---1---②---1---①---4---❸      
❷---3---'
❸---5---'
         :       :       :
1st    (1,❶)   (2,❶)   (3,❶)    (最短距離,始点グループ)
2nd    (3,❷)   (4,❷)   (4,❸)
答え    1        2        4

1stが自身と同じ値の始点グループだったら、2ndを採用すればよい。

このようにしても、計算量は、上位 $k$ グループまでを保持するとして(今回は $k=2$)、通常のDijkstraの $k$ 倍という定数倍で収まる。

ただし、通常のDijkstraで行うような枝刈りは、このカスタマイズにおいても行う必要がある。

実装について

上位 $k$ 番目まで保持するDijkstraにおいては、以下のサイトで言及されているDijkstraの2種類の実装のうち、 1番目を元にした方が書きやすいかも。

というのも、暫定距離配列 dist をいつ更新するかにおいて、

なので、2番目は後から更新されることがあり得る。(1番目は確定してからdistに入れるので「暫定」でもない)

後から更新されうると、新しい値で dist をどのように更新すべきかについて

とせねばならず、常に「上位 $k$ 以内の最も劣る値」を取得できなければならない。
ソートなどに計算量を費やすことになり、大変である。

一方、1番目の実装であれば、$k$ 回まで取り出された順に確定していけばよいので、実装も計算量も楽になる。

最短距離のみのDijkstraなら、2番目の実装の方が、キューに突っ込まれる要素を抑えられ、 チェック済みかどうかを管理する配列も持たなくていいのでメモリや計算量的に優しいが、、、 上位 $k$ 番目までを求める場合はそうとは限らないんだね。

Python3