Ford-Fulkerson法と最大流問題

最大流問題(最大フロー問題)とは、単一の始点から単一の終点へのフローネットワークで最大となるフローを求める問題です。各地点が水道管でつながっていて、どのように水を流せば一番多くの水を流せるかという問題と考えることもできます。

下の図はで頂点が6つ、頂点同士をつなぐ辺が9つあります。では頂点sからtまで流すことができる水の量はどうなるでしょうか?

始点から終点まで流すことができるパスを求め、フローの流量を求め、通過した辺の容量をそのぶん減らす、また始点から終点まで流すことができる別のパスを求めフローを流すのを繰り返すという方法でよさそうですが、それだとうまくいかない場合があります。

上の例は簡単な図なので考えるまでもなく、答えは35です。0→1→3を20、0→2→3を15、あわせて35です。

ところが0→1→2→3というパスを最初に選択して10のフローを流してしまうと(下図)、0→1→3には10のフローを流したあと0→2→3には5のフローしか流せず合計は正しい値になりません。

そこで鍵となるのが逆辺です。ある辺にフローを流すと、その辺の容量は流した分だけ減り、逆向きの辺の容量が流した分だけ増えるという考え方です。

この方法だと上のような要領が悪いパスを選んだとしても(下図)、0→1→3に10のフローを流して、0→2→3に5のフローを流し、0→2→1→3に10のフローを流すことができるので合計は35となり正しい値を得ることができます。

フローをどれだけ追加できてどれだけ戻すことができるかを重みつき有向グラフで表したものを残余ネットワークといいます。

下の動画の説明はわかりやすいです。

以前、C#でFord-Fulkerson(フォード・ファルカーソン)のアルゴリズムを用いて最大流問題を解く処理を実装しましたが、今回はJavaScriptで実装することにします。

参考:最大流問題を解く Ford-Fulkerson法

実装する

まずHTML部分を示します。

初期値(入力例)をセット

頂点の数と始点、終点、各辺の流せる量を指定します。どのように指定するかわかるようにページが読み込まれた段階で初期値がセットされるようにしておきます。

index.js

クリアボタンがクリックされたら入力されたデータを消去します。

最大流を計算する

計算ボタンがクリックされたら最大流を計算します。

幅優先探索で増加道を探す

SearchPath関数は幅優先探索でs, tまでたどり着くパスを探します。あればtrue、なければfalseを返します。