かしのブログ

競技プログラミングとか

AtCoder Regular Contest 049 - ぬりまーす

問題

 N頂点のグラフのいくつかの頂点に、以下のような制約を満たすように色を塗る。

  • タイプ1:ある頂点 xに色を塗るとき、既に頂点 yに色が塗られてなければならない
  • タイプ2:ある頂点 uに色を塗るとき、既に頂点 vに色が塗られていてはいけない

全ての制約を満たすときに塗れる頂点の最大数を求める。

atcoder.jp

考察

タイプ1の制約は、「頂点 y \rightarrow xの順番で塗る」ということ。これを「 y \rightarrow x」と表記する。 ある頂点 xが塗れないとき、 y \rightarrow xを満たし塗れない頂点 yが存在する、もしくは x \rightarrow \cdots \rightarrow xとなっているとき(「 xを塗る前に xが塗られている」必要がある)である。後者は、有向グラフの閉路検出で、強連結成分分解が使える。2つ以上の頂点を含む連結成分から連鎖的に塗れない頂点がわかる。

タイプ2の制約は、次の2パターンのどちらかを満たせばよい。

  •  u \rightarrow v
  • 頂点 uを塗らない

前者はタイプ1と同一である。Bの上限が小さいので、タイプ2の制約を総当たりで2パターンにどちらかに振り分ける。

実装

塗る順番が y \rightarrow xであっても、DFSで連鎖的に塗れない頂点を調べるために、 x \rightarrow yの有効辺を追加して強連結成分分解を行う。

頂点 uを塗らない場合は、ダミーの頂点 u^\prime u u \rightarrow u^\prime\rightarrow uであることにする。

atcoder.jp