Dinic 法でのボトルネックは, 各ステップで, dfs によりブロッキングフローを求める部分でした.
前回は, だったこの部分を に落としたアルゴリズムを二つ紹介しました.
今回は, ここを , 従って, 全体では にするアルゴリズムを紹介します.
前回の二つは, ある意味でまとめて流そうという感じのアルゴリズムでした.
今回のは, どちらかと言えば, Dinic 法の dfs を単純に速くする感じです.
突然ですが, Link/Cut Tree と呼ばれるデータ構造があります.
Link/Cut Tree は, 有向森(根付き木がいくつかあるもの) に関して, 色々なクエリを処理させられる, 割と強力なデータ構造です.
まず, 森の形状を変えるための基本的なクエリとして次の 4 つが挙げられます.
他に, 例えば次のようなクエリを処理出来ます.
これらのようなクエリを, (償却計算量の意味で)対数オーダーで処理出来るデータ構造です.
誤解を恐れずに言えば, 切れる Union-Find Tree で, 木構造っぽいクエリの他に, 頂点を端点とする path に Segment Tree と同じような操作をサポートさせられるような感じです.
次の 3 つを読むとよいです.
自分が実装した時の印象は, 次のような感じでした.
参考文献1 の 26 ページ下部のあたりから読むのが手っ取り早いです.
Dinic 法の dfs の途中の状態を見てみましょう.
各頂点に対し, 今見ている辺を, なる変数に格納していましたが, これに対応する辺に注目します.
例えば, 次の図のようになっています.
に対応する辺だけ見ると, 次の図のように, ( に近い側を根として持つ, 内側向きな有向)森になっています.
dfs を進めるのあたって, 森の上では次のような操作が行われています.
ちょっと考えると, 次の操作をサポートする Link/Cut Tree を用意すれば, 対応する操作を Link/Cut Tree 上で実現出来る事が解ります. (容量は, 辺ではなく, 辺の下側の頂点に持たせます)
具体的には, 次のようにすればよいです.
ここで, に対する は, 次のような操作です.
また, 実装がややこしくなりますが, Dinic 法と同じく, bfs と dfs を逆から行うことが出来ます.
各辺につき, 高々一回ずつ , する.
また, とか は, 高々 と同じくらいしかしない.
従って, ブロッキングフローを求めるのに, , 合計 .
ここ に置いておきました.
拡張のしやすさとか, 機能と拡張性を犠牲にして, 速さとかを重視しているので, Link/Cut Tree 部分がごちゃごちゃしています. (つってもそんなに速くないかもしれないですが.)
あと, L/C Tree は, Dinic だとこういうクエリしか来ないからとかいうので, 本来であれば必要なコードを削っていたりもするので, このままライブラリに転用はしないほうが良いです.
例によって, どういうデータが欲しいかに従って, 自分で計測して下さい.
前回と同じデータで, Dinic 法と比較してみると, 次のようになっていました.
前と同様, グラフの構築にかかる時間は無視しています.
ケース | 頂点数 | 辺数 | Dinic (sec) | L/C Dinic (sec) | Wave (sec) |
---|---|---|---|---|---|
ランダムを80ケース(合計) | 5000 | 1000000 | 1.9 | 1.8 | 5.3 |
ランダムを40ケース(合計) | 50000 | 1000000 | 2.0 | 2.1 | 10.0 |
ランダムを13ケース(合計) | 500000 | 1000000 | 1.9 | 2.3 | 10.0 |
密なランダムを5ケース(合計) | 5000 | 約 | 2.1 | 1.1 | 3.2 |
完全グラフを15ケース(合計) | 2000 | 2.0 | 1.9 | 3.6 | |
ワーストケース1つ目 | 7000 | 13997 | 1.9 | 5.3 | 5.1 |
ワーストケース2つ目 | 628 | 33491 | 2.0 | 0.7 | 0.1 |
実測でも, 思ったほど遅くないです.
ワーストケースの一つ目は, dfs が 回必要だけど, 各 dfs では割と自明なフローをひょいと流すだけなので, ブロッキングフローを探すアルゴリズムによる差は出にくく, 逆に定数倍が大きく出てくるので, そんな感じになっています.
まぁ, 使うかどうかは置いておいて, 面白い.
やる気と時間があれば, Push/Relabel 法について.
やりたい事が大体終わってきたので, 続かない確率割と高まっている.
1. は no title から読めます.