E – Art Gallery on Graph

N 頂点 M 辺の単純無向グラフがあり、頂点 p[i] に体力は h[i] の警備員がいる。ひとり以上の警備員がたどり着ける頂点はどれか?すべて列挙せよというのが問題の趣旨です。

警備員の体力がすべて同じなら多始点の幅優先探索をして、距離が h 以内の頂点をすべて列挙すればいいのですが、この問題は警備員の体力がそれぞれ異なっています。さてどうすればよいのでしょうか?

ここではダイクストラ法の反転させたようなアルゴリズムを採用します。

ダイクストラ法とは?

ダイクストラ法は以下のような方法です。

頂点数と同じ長さの配列 D を用意し、n が開始地点であるときは D[n] = 0、それ以外の要素は ∞ で初期化する。
優先度付きキュー( priority が小さいものが先に取り出される)に開始地点 s を格納する。このとき priority は 0 とする。
優先度付きキューから値をとりだす。この値を u とする。この段階で開始地点から u までの移動に必要な距離が D[u] であると確定する。
u から移動可能な頂点 v と移動に必要な距離 w(u, v) を調べる。
D[v] よりも D[u] + w(u, v) のほうが小さい場合は D[v] を D[u] + w(u, v) で更新して優先度付きキューに v を格納する。このとき priority は更新された D[v] とする。そうでないときは何もしない。
優先度付きキューが空になるまで上記を繰り返す。処理が終わったとき D[v] の値が s から v までの移動に必要な距離となっている。

変則的な多始点ダイクストラ法

この問題の場合は、体力は h[i] の警備員がたどり着ける頂点を知りたいので最初に警備員がいる頂点 v は D[v] = h[v]、それ以外の頂点はD[v] = h[v] で初期化しておきます。そして警備員が移動可能な頂点には体力を 1 減らした警備員のコピーを配置していきます。警備員をこれ以上コピーできなくなったら警備員がいる頂点を列挙すればこれが答えとなります。

まず指定された頂点から指定された距離内にある頂点を取得するためのクラスを定義します。

Solverクラスから解を求めます。