AtCoder NoviStepsを埋めてみる(26) 幅優先探索 2Qの続きです。今回も幅優先探索(BFS)です。やや難しめの問題に挑戦します。

D – Reachability Query 2

D – Reachability Query 2

問題の概要

N 頂点 M 辺の有向グラフが与えられる。
頂点には色がつけられていて最初はすべて白色である。
Q 個のクエリが与えられるので順番に処理せよ。
クエリ 1:頂点 v を黒色にする。
クエリ 2:頂点 v から辺を辿って黒色の頂点に到達可能かどうか判定する。

クエリ 2 が来るたびに頂点 v から黒い頂点にたどり着けるか調べていると時間がかかります。そこで辺を逆向きにしてクエリ 1 が来たらそこからたどりつける頂点をすべて黒で塗ります。この方法だと黒く塗られた頂点は以降は探索対象から外れるため処理にかかる時間を短縮できます。

D – XOR Shortest Walk

D – XOR Shortest Walk

問題の概要

N 頂点 M 辺の有向グラフが与えられる。
辺 i は頂点 A[i] から頂点 B[i] への重み W[i] の有向辺である。
頂点 1 から頂点 N への walk のうち、walk に含まれる辺の重みのビット単位 XOR の最小値を求めよ。

単純な頂点 1 から頂点 N への最短経路長を問う問題ではなく、辺の重みの XOR を計算しなければなりません。このような場合、どうすればよいのでしょうか?

こんなときに使えるのが「頂点倍化」です。頂点倍化とは付随する状態について新たに点を作って、その状態遷移について辺を貼ることです。

頂点 1 から各頂点 への walk について walk に含まれる辺の重みのビット単位は 1024 通り考えられます。そこで各頂点の訪問済みフラグを 1024 個定義します。

あとは幅優先探索をして seen[N – 1, i] = true である最小の i を出力すればこれが解となります。

D – Snaky Walk

D – Snaky Walk

問題の概要

H 行 W 列のグリッドがある。’S’ から ‘G’ まで移動することはできるだろうか?
ただし障害物マスやグリッドの外に移動することはできず、また縦移動と横移動を 1 回ずつ交互に行わなければならない。
可能ならば移動回数の最小値を求めよ。

「縦移動と横移動を 1 回ずつ交互におこなう」ということなので、マスを白黒の市松模様に塗り、「白マスは上下のみ、黒マスは左右のみ移動可」とする場合と白マスと黒マスの役割を入れ替えた場合の 2 パターンを考えます。

グリッド上の幅優先探索をおこない最短経路長を比較します。小さいほうが出力すべき解です。

D – Repeatedly Repainting

D – Repeatedly Repainting

問題の概要

H 行 W 列のグリッドがあり、各マスは白か黒で塗られている。
以下の操作を 10^100 回おこなう。操作を終えた後に各マスが何色で塗られているか求めよ。
(操作)
操作前に黒く塗られているマスは、白く塗り替える。
操作前に白く塗られているマスは、そのマスに隣接(8方向)するマスで黒で塗られているものが存在するときだけ黒く塗り替える。

1 回以上の操作を行って得られるマス目について、黒く塗られたマスは、隣接する白く塗られたマスを持ちます。問題の条件より黒く塗られたマスはそれ以降交互に色を変えることになります。

そこで 1 回だけ操作を行い、その後に初めてマスが黒く塗られるタイミング(の偶奇)が各マスについてわかればこの問題を解くことができます。

あとは多始点型の幅優先探索をして 1 回だけ操作をおこなった状態における黒マスからの最短経路長を求めればよいです。奇数であれば ‘#’, 偶数であれば ‘.’ です。黒マスが存在しない場合はすべて ‘.’ です。

D – Go Straight

D – Go Straight

問題の概要

H 行 W 列のグリッドがある。
‘#’ が書かれているマスに立ち入ることはできない。
‘o’ が書かれているマスでは直前の移動と同じ方向に移動しなければならない。
‘x’ が書かれているマスでは直前の移動と同じ方向に移動することはできない。
上記の条件で ‘S’ から ‘G’ まで移動することはできるだろうか?
可能ならば移動方法をひとつ出力せよ。

‘o’ や ‘x’ マスにおいては直前の移動方向が問題になるので訪問済みフラグを 4 つ用意します。Queue に格納する情報がひとつ増えますが、あとは通常の幅優先探索と同じです。

D – Go Stone Puzzle

D – Go Stone Puzzle

問題の概要

N + 2 個のマスが横一列に並んでいて、マス 1 からマス N には白または黒の石が 1 個ずつ置かれている。
「石が 2 個並んでいる箇所を選び、その 2 個の石を順序を保って空きマスに移す」という操作を繰り返して A の状態から B の状態へ移行することはできるだろうか? 可能なら操作回数の最小値を出力せよ。

A にふたつ並んだ空きマスを 1 文字として追加した場合、この文字列が取りうる場合の数は (N + 1)! / (B! * W!) です。これは最大でも 51,480 通りにしかなりません。なので幅優先探索をすることで B と一致させるための最短手数を求めることができます(下記コードではふたつ並んだ空きマスを “..” の 2 文字で表している)。

D – Grid and Magnet

D – Grid and Magnet

問題の概要

H 行 W 列のグリッドがある。
‘#’ が書かれているマスは磁石であり立ち入ることができないだけでなく、その隣に移動してしまうと吸い付いてしまい、そこから動くことができなくなる。
磁石が置かれていないマスの中における、マスの自由度の最大値を求めよ。

単純な訪問済みフラグだと磁石の隣への移動を考えるときに困るので工夫をします。

訪問済みフラグを bool 型ではなく int 型にして探索開始点によって 1 以上の異なる値で埋めることにします。探索開始点がすでに 1 以上の値のときはそこからは探索を開始しません。探索中に異なる値があった場合は上書きします。各探索開始点からもっとも更新回数が多かったものが求めるべき解となります。

D – Medicines on Grid

D – Medicines on Grid

問題の概要

H 行 W 列のグリッドがある。
‘#’ が書かれているマスに立ち入ることはできない。
上下左右に隣り合う空きマスへエネルギーを 1 消費して移動することができる。
エネルギーが 0 の状態で移動することはできない。
グリッドには合計で N 個の薬がある。i 番目の薬は空きマス (R[i] ,C[i]) にあり、使う使わないを選ぶことができる。使うと薬はなくなりエネルギーが E[i] に変更される(必ずしもエネルギーが増えるとは限らない)。
‘S’ から ‘G’ まで移動することはできるだろうか?

まず薬 i からほかの薬やゴールまで移動できるか調べます。最短経路長が E[i] 以内であれば移動可能です。頂点を N + 1 個用意して薬 i から薬 j まで移動可能であれば、頂点 i から 頂点 j へ辺を張ります。また薬 i からゴールまで移動可能であれば、頂点 i から 頂点 N へ辺を張ります。

スタート地点に薬がない場合はエネルギーが 0 なので移動できず “No” が解となります。そうでない場合はスタート地点に相当する頂点から頂点 N までたどり着ける場合は “Yes” そうでない場合は “No” です。

D – Synchronized Players

D – Synchronized Players

問題の概要

N 行 N 列のグリッドがある。グリッド上にふたりのプレイヤーがいる。
上下左右のいずれかの方向を決め、各プレイヤーをその方向に隣接するマスへの移動可能なら移動させる。
このような操作を繰り返してふたりのプレイヤーを同じマスに集めることはできるだろうか?
可能であればそのために必要な操作回数の最小値を求めよ。

ふたりのプレイヤーの位置情報で幅優先探索をすればよいです。ふたりのプレイヤーの位置の組み合わせは N^4 通りあります。なので時間計算量も O(N^4) ですが、N の最大値は 60、実行時間制限は 4 秒なので充分間に合います。

E – Prerequisites

E – Prerequisites

問題の概要

1 から N までの番号がついた N 冊の本がある。
本 i には C[i] 冊の前提となる本があり、そのうち j 冊目は本 P[i,j] であり、これらをすべて読む必要がある。
本 1 を読むためにそれ以外に読まなければならない本の番号を読むべき順に出力せよ。

N 個の頂点を用意して頂点 i から頂点 P[i,j] に向けて辺を張ります。これは本 i を読むためには本 P[i,j] をすべて読まなければならないことを意味しています。そして頂点 1 から幅優先探索をしたときに訪問した頂点が読むべき本の集合となります。

それらを読むべき順に出力する方法ですが、頂点 P[i,j] から頂点 i に向けて辺を張ったグラフを構築してトポロジカルソートすればよいです。ただし、新しくグラフを構築するのではなく、読むべき本の集合を求めるために使ったグラフをトポロジカルソートして逆順にしたほうが速いです。このなかから集合に含まれているものだけを出力します。

E – Nearest Black Vertex

E – Nearest Black Vertex

問題の概要

N 個の頂点と M 本の辺からなる単純連結無向グラフが与えられる。
「頂点 P[i] と「黒で塗られた頂点のうち頂点 P[i] からの距離が最小であるもの」の距離がちょうど D[i] である」という条件を満たす 1 個以上の頂点が黒で塗られているグラフを示せ。

以下の方法が思いつきます。

最初はすべての頂点を黒で塗る。
頂点 P[i] から距離が D[i] 未満のものを白で塗り直す。

ただし、これだけでは落ちるケースがあります。頂点 P[0] から距離が D[0] 未満のものを白で塗り直したときには頂点 P[0] から距離がちょうど D[0] であるものが存在したけど、頂点 P[1] から距離が D[1] 未満のものを白で塗り直したときに頂点 P[0] から距離がちょうど D[0] であるものがすべて白で塗り直されてなくなっている場合があるからです。なので K 個の処理が終わった後、頂点 P[i] から距離が D[i] と同じものが本当に存在するか確認する処理が必要です(十分性の検証)。

E – Swap Places

E – Swap Places

問題の概要

N 頂点 M 辺の単純無向グラフがあり、すべての頂点は赤か青のいずれか一方で塗られている。
高橋君が頂点 1 に、青木君が頂点 N にいる。
2 人が同時に、今いる頂点に隣接している頂点のいずれか 1 個に移動する。
ただし、高橋君の移動先の頂点の色と、青木君の移動先の頂点の色は異なる必要がある。
高橋君が頂点 N に、青木君が頂点 1 にいる状態にできるだろうか?
可能である場合は必要な行動回数の最小値を答えよ。