競プロ備忘録

競プロerの備忘録

ABC62F/ARC74D - Lotus Leaves

フローの問題を履修しているときに出くわしましたが、解説とちょっとグラフの作り方が違ったので。

解法

葉であるマス目を頂点として同じ行or同じ列どうしの頂点を辺で接続し、フローグラフを構築する。
すると、Sourceを SDestination Tとしたときの最小カットを求めることで、問題の解を求めることができる。

今回はどのように容量を持たせるかというところが問題だが、問題設定的に葉(=頂点)を落とさないといけないので、頂点が容量を持てるとうれしい。
そこで、各頂点を in, outの2つに分割し、他の頂点から接続されるポイントを inに集約し、逆に他の頂点へ向かうポイントを outに集約する。さらに、 in, outの間を容量 1の辺で接続する。他の頂点への辺の容量は \inftyとしておく。

このようなフローグラフのボトルネックは必ず各頂点の in, outの間になってくれるので、 S _ {out}から T _ {in}に向かってフローを流すことで、それらの中のどれかがカットされ、答えが求まる。

注意する点としては、 S Tが同じ行or同じ列にある場合は -1を出力する必要があるが、これはグラフ構築の時点で取り除かないと良くないことが起こると思われる。
(実装次第だと思うが、最小カットが \inftyになって出力されたり、フローライブラリの中でオーバーフローを起こしてヘンテコな値が出てくるかもしれない)

頂点数が V = 2HW、辺の数が最悪で E = H(H-1)/2 * W + W(W-1)/2 * H = HW(H+W-2)/2となるので、Dinic法で解くとすると O(|V|^{2}E)であるから、 O(H^{2}W^{2}(H+W))程度か?
本当に間に合うんか?と疑いたくなるが、Dinic法に祈りながら提出すると、別にTLギリギリということはなく余裕でACになる。

実装例は以下の通り。

Submission #37100569 - AtCoder Regular Contest 074