国立大学法人 北海道大学
工学部情報エレクトロニクス学科
情報理工学コース情報知識ネットワーク研究室
学部三年 大泉翼
はじめに
本スライドは蟻本に沿った内容になります。
二部マッチングの証明のみ自分で考えたもので、不備がある可能性
がございます。どうぞご指摘下さい。
また、グラフに逆辺を張る操作を図にするので、図が見えにくいです
が、頑張ってみてください。
目次
• 最大フロー、最小カットのお話
• 競プロのお話
目次
• 最大フロー、最小カットのお話
• 競プロのお話
前提知識
𝛿− 𝑣 := 頂点 v へ入ってくる辺の集合
𝛿+ 𝑣 := 頂点 v から出ていく辺の集合
二部グラフ
以下の性質を満たす頂点集合の分割 (S, 𝑉 ∖ 𝑆)が存在する
-グラフのどの辺も 𝑆 の要素の頂点と、 𝑉 ∖ 𝑆 の要素の頂点とに接続している
最大フローとは
有向グラフ 𝐺 = 𝑉, 𝐸 において、各有向辺 𝑒 に負でない実数 𝑐(𝑒), 𝑒 ∈ 𝐸 が定
められているとする。
[定義]
フローとは、 𝐺 の各有向辺 𝑒 に負でない値 𝑓 𝑒 を割り当てる関数 𝑓 が存在し、次
の性質を満たすものをいう。
・ e ∈ 𝐸に対して f e ≤ 𝑐 𝑒
・ v ∈ 𝑉 ∖ {𝑠, 𝑡} に対して 𝑒 ∈ 𝛿− 𝑣 𝑓 𝑒 = 𝑒 ∈ 𝛿+ 𝑣 𝑓(𝑒)
𝑒 ∈ 𝛿+ 𝑠 𝑓 𝑒 = 𝑒 ∈ 𝛿− 𝑡 𝑓(𝑒) = フロー値
フロー値が最大になるフローを最大フローという
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
𝑠
𝑢5
𝑢4
𝑡
4
2
1
4
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
𝑠
𝑢5
𝑢4
𝑡
1/4
2/2
1/1
2/4
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
𝑠
𝑢5
𝑢4
𝑡
4
2
1
4
1
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
𝑠
𝑢5
𝑢4
𝑡
2/4
2/2
1/1
3/4
1/1
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
𝑠
𝑢5
𝑢4
𝑡
4
2
1
4
1000000000
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
𝑠
𝑢5
𝑢4
𝑡
1/4
2/2
1/1
2/4
0/1000000000
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
𝑠
𝑢1
𝑢3
𝑢2
𝑢5
𝑢4
𝑡
1
4
3
4
2
1
1 2
4
2
1
最大フローとは
重みつき有向グラフ G において
各辺の容量を超えずに s から t に送ることのできる量の最大値
𝑠
𝑢1
𝑢3
𝑢2
𝑢5
𝑢4
𝑡
1/1
1/4
3/3
1/4
2/2
1/1
1/1 0/2
3/4
2/2
1/1
貪欲のアルゴリズム?
• (1)流せる余地のある辺のみを使って s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 8
2
10
6
t
5
3
6
貪欲のアルゴリズム?
• (1)流せる余地のある辺のみを使って s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 8
2
10
6
t
5
3
6
貪欲のアルゴリズム?
• (1)流せる余地のある辺のみを使って s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 8
2
5/10
5/6
t
5/5
3
6
貪欲のアルゴリズム?
• (1)流せる余地のある辺のみを使って s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 8
2
5/10
5/6
t
5/5
3
6
貪欲のアルゴリズム?
• (1)流せる余地のある辺のみを使って s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 5/8
2
10/10
5/6
t
5/5
3
5/6
貪欲のアルゴリズム?
• (1)流せる余地のある辺のみを使って s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 5/8
2
10/10
5/6
t
5/5
3
5/6
終了!
答えは10!
貪欲のアルゴリズム?
• (1)流せる余地のある辺のみを使って s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 5/8
2
10/10
5/6
t
5/5
3
5/6
でも、
本当は?
貪欲のアルゴリズム?
• (1)流せる余地のある辺のみを使って s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 6/8
1/2
10/10
4/6
t
5/5
3
6/6
正しい答え
11!
貪欲のアルゴリズム?
• 両者の流量の差に着目してみる
𝑠
𝑢2
𝑢1
𝑢3 +1
+1
-1
t
+1
貪欲のアルゴリズム?
• 両者の流量の差に着目してみる。
• -1 はそれまでのフローを押し戻す操作に相等する。
𝑠
𝑢2
𝑢1
𝑢3 +1
+1
-1
t
+1
貪欲のアルゴリズム?
• 両者の流量の差に着目してみる。
• -1 はそれまでのフローを押し戻す操作に相当する。
• 流れている流量分だけ逆辺を追加して、フローを押し戻せるようにす
る。
𝑠
𝑢2
𝑢1
𝑢3 +1
+1
-1
t
+1
Ford-Fulkersonのアルゴリズム
• (1)流す余地のある辺と、流した容量分の逆辺のみを使って、 s から
t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 8
2
10
6
t
5
3
6
Ford-Fulkersonのアルゴリズム
• (1)流す余地のある辺と、流した容量分の逆辺のみを使って、
s から t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 5/8
2
10/10
5/6
t
5/5
3
5/6 この状態から
Ford-Fulkersonのアルゴリズム
• (1)流す余地のある辺と、流した容量分の逆辺のみを使って、 s から
t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 5/8
2
10/10
5/6
t
5/5
3
5/6
流れている分だけ
逆辺をはり10
5
5
5
5
Ford-Fulkersonのアルゴリズム
• (1)流す余地のある辺と、流した容量分の逆辺のみを使って、 s から
t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 5/8
2
10/10
5/6
t
5/5
3
5/6
パスを見つける!
10
5
5
5
5
Ford-Fulkersonのアルゴリズム
• (1)流す余地のある辺と、流した容量分の逆辺のみを使って、 s から
t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 6/8
1/2
10/10
4/6
t
5/5
3
6/6
10
4
5
5
5
Ford-Fulkersonのアルゴリズム
• (1)流す余地のある辺と、流した容量分の逆辺のみを使って、 s から
t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 6/8
1/2
10/10
4/6
t
5/5
3
6/6
10
4
6
5
5
1
逆辺を張りなおしても、
パスが見つからない
Ford-Fulkersonのアルゴリズム
• (1)流す余地のある辺と、流した容量分の逆辺のみを使って、 s から
t へのパスを見つける
• (2)見つかれば目一杯流して、(1)に戻る。見つからなければ終了
𝑠
𝑢2
𝑢1
𝑢3 6/8
1/2
10/10
4/6
t
5/5
3
6/6
10
4
6
5
5
1
逆辺含めたグラフを
残余グラフという
Ford-Fulkersonのアルゴリズム
• アルゴリズムの正当性は後程
• パスを見つけては更新の繰り返し
• DFS でパスを見つける
• 最大フローの流量を F とすると高々 F 回 DFS が行われる
• 最悪計算量は 𝑂 𝐹 𝐸 + 𝑉
カットとは
[定義]
頂点集合の任意の分割 S, V ∖ 𝑆 を考える。
S から V ∖ 𝑆 に出ていく辺の集合をカットと言い、 S, V ∖ 𝑆 と表す。
特に、s ∈ 𝑆 , t ∈ 𝑉 ∖ 𝑆のとき𝑠 − 𝑡 カットという
s-t カットに含まれる辺全てを削除すると、 𝑠 − 𝑡パスがなくなる
カットに含まれる辺の容量の総和をカットの容量という
最小カットとは、任意の 𝑠 − 𝑡 カットのうち、カットの容量が最小のもの
カットとは
C = { 𝑢1, 𝑢4 , 𝑢2, 𝑢4 , 𝑢2, 𝑢5 , 𝑢3, 𝑢5 } はカット? はい。
カットの容量は? 8です。
𝑠
𝑢1
𝑢3
𝑢2
𝑢5
𝑢4
𝑡
1
4
3
4
2
1
1 2
4
2
1
カットとは
C = { 𝑠, 𝑢1 , 𝑠, 𝑢2 𝑠, 𝑢3 } はカット? はい。
カットの容量は? 8です。
𝑠
𝑢1
𝑢3
𝑢2
𝑢5
𝑢4
𝑡
1
4
3
4
2
1
1 2
4
2
1
カットとは
C = 𝑢1, 𝑢4 , 𝑢4, 𝑢5 𝑢5, 𝑡 はカット? いいえ。
𝑠
𝑢1
𝑢3
𝑢2
𝑢5
𝑢4
𝑡
1
4
3
4
2
1
1 2
4
2
1
カットとは
C = { 𝑠, 𝑢1 , 𝑠, 𝑢2 𝑢3, 𝑢5 } はカット? はい。
カットの容量は? 5です。
𝑠
𝑢1
𝑢3
𝑢2
𝑢5
𝑢4
𝑡
1
4
3
4
2
1
1 2
4
2
1
最大フロー・最小カットの定理
[定理]
任意のネットワークにおいて、最大フローの値は、最小カットの容量に
等しい
𝑠
𝑢1
𝑢3
𝑢2
𝑢5
𝑢4
𝑡
1/1
1/4
3/3
1/4
2/2
1/1
1/1 2
3/4
2/2
1/1
証明
• 証明したいことは二つ
• Ford-Fulkerson のアルゴリズムの正当性
• 最大フロー・最小カットの定理
証明
[証明の流れ]
1) 任意のフロー f の流量 ≤ 最小カットの容量
2) Ford-Fulkerson で得られたフロー f’の流量 = 最小カットの容量
この二つを示すことができれば、
f’ が最大フローであり、同時に最大フロー・最小カットの定理を示せる。
任意のフロー f の流量 ≤ 最小カットの容量
任意のフロー 𝑓と任意のカット (S, V∖S) を考える
(𝑓の流量) = 𝑒 ∈ 𝛿+ (𝑠) 𝑓(𝑒) であり、
𝑣 ∈ 𝑆 ∖ 𝑠 に対して 𝑒 ∈ 𝛿−(𝑣) 𝑓(𝑒) = 𝑒 ∈ 𝛿+(𝑣) 𝑓(𝑒)であるので
(𝑓の流量) = (Sから出ていく辺の流量) – (Sに入ってくる辺の容量)
≤ (カットの容量)
𝑠
𝑢2
𝑢1
𝑢3
𝑓(𝑒1)
t
𝑓(𝑒2)
𝑓(𝑒4)
𝑓(𝑒3) 𝑓(𝑒5)
𝑓(𝑒7)
𝑓(𝑒6)
f’の流量 = 最小カットの容量
f’ に対する残余グラフにおいて、
s-vパスの存在するような頂点 v からなる集合を S とする。
f’ の残余グラフにおいてs-tパスが存在しないので、(S, V∖S)は s-t カットとなる。
また, S の性質より
S から V ∖ Sに向かう辺 e について f’(e) = c(e)
V ∖ S から S に向かう辺 e について f’(e) = 0
したがって
(f’の流量) = (Sから出る辺の流量)
- (Sに入る辺の流量)
= (カットの容量)
𝑠
𝑢2
𝑢1
𝑢3 6/8
1/2
10/10
4/6
t
5/5
3
6/6
10
4
6
5
5
1
実装例(C++)
目次
• 最大フロー、最小カットのお話
• 競プロのお話
競プロの話
• フローのアルゴリズムは複雑なので、ライブラリ化するのがおすすめ
• 最大流を計算するクラスを用意
• メンバ関数は以下の二つ
- add_edge(int from, int to, int cap) := 辺を追加する
- max_flow(int s, int t) := s から t への最大フロー値を求める
競プロの話
ブラックボックス
身も蓋もない話
• 最大流問題を解くアルゴリズムはFord-Fulkerson法のほかに Dinic法
が知られている。
• Dinic法のオーダーはO(E V^2) だが、実際には爆速に動く
• こっちを使っているひとが多いように感じる
問題の解き方
• 考察する
• あ、これフローっぽいな or カットっぽいな
• グラフをいい感じに作る
• ライブラリをペタリ
•AC
問題(KUPC2014 H)
https://qupc2014.contest.atcoder.jp/tasks/qupc2014_h
[問題概要]
M 頂点 N 辺 の重みつき有向グラフと整数 P、さらに頂点番号 𝐿0, 𝐿1, … 𝐿 𝐺−1 が与
えられる。各頂点には魔法使いが一人づつ存在し、𝐿𝑖 (0 ≤ 𝑖 ≤ 𝐺 − 1) にいる魔
法使いは無制限に魔力を得ることができる。各辺の重みを超えないようにうまく魔
力を伝達した時に、頂点 0 に P 以上の魔力を送ることができるかどうかを答えよ
[制約]
1 ≤ 𝑁 ≤ 500
1 ≤ 𝑀 ≤ 500
考察
最大フローを求める問題に帰着できそう
頂点が複数設定される。どう処理するか?
4
32
0
1
200
50
100
100
入力例3
4 5 100 2
3 4
1 0 200
2 1 50
3 2 100
4 2 100
考察
図のように架空の s 頂点を追加して…
4
32
0
1
200
50
100
100
S
入力例3
4 5 100 2
3 4
1 0 200
2 1 50
3 2 100
4 2 100
考察
図のように架空の s 頂点を追加して…
容量 INF の辺を張り…
4
32
0
1
200
50
100
100
S
入力例3
4 5 100 2
3 4
1 0 200
2 1 50
3 2 100
4 2 100
INF
INF
考察
図のように架空の s 頂点を追加して…
容量 INF の辺を張り…
最大フローを流せばよい!
4
32
0
1
50/200
50/50
0/100
50/100
S
入力例3
4 5 100 2
3 4
1 0 200
2 1 50
3 2 100
4 2 100
50/INF
0/INF
実装例 (C++)
問題 (ABC010 D)
https://beta.atcoder.jp/contests/abc010/tasks/abc010_4
[問題概要]
SNS の友人関係を表す無向グラフが与えられる。
なぎさちゃんは高橋君に自分以外の女と連絡を取ってほしくない。
なぎさちゃんは以下のような工作ができる。
- 友人関係を一つ解消
- 一人のパスワードを変更し、メッセージを閲覧不可能にする
なぎさちゃんが工作を行う回数の最小値を出力してください
[制約]
1 ≤ 𝑉 ≤ 100
考察
• このような図で考えてみる
高
女
女
女
考察
• 最適解は 2
高
女
女
女
考察
• 工作のパターンが二種類あるのが面倒
高
女
女
女
考察
• 図のように架空の頂点を追加すると、辺の削除だけを考えることが
できる
高
女
t
s
女
女
女
考察
• 最小カットに帰着できた!!
高
女
t
s
女
女
女
考察
• 別の例
高
女
女
女
考察
• グラフをちょっと移動
高
女
女
女
考察
架空の頂点に辺を張る
高
女
女
女
女
考察
最小カット!!
高
女
女
女
女
実装例(C++)
• s ノードと t ノードに何番を割り振るかを
• 定義してしまう。
• s := 0, t := n
問題 (ACPC 2018 I)
https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2018Day2/problems/I
[問題]
文字列のリストが与えられ、しりとりを以下のルールで行う。
1) まず最初に、リストの中から好きな文字列を一つ選び、その文字列をリストから
除外する。
2) 続いて、一つ前に選んだ文字列の最後の一文字が、最初の一文字である文字
列をリストから一つ選ぶ。
3) 選んだ文字列をリストから除外する。
この後、2., 3.を交互に繰り返すことになる。
さて、このしりとりを2.でリストから選べる文字列がなくなるまで続けたとしよう。 こ
のときに、最後に選んだ文字列の「最後の一文字」としてあり得る文字をすべて列
挙したい。
問題 (ACPC 2018 I)
https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2018Day2/problems/I
[制約]
1 ≤ 𝑁 ≤ 104
1 ≤ 𝑠𝑖 ≤ 100
考察
[入力]
7
she
sells
sea
shells
by
the
seashore
与えられた入力をグラフにしてみる(自己ループは無視)
S e
at
b y
考察
[入力]
7
she
sells
sea
shells
by
the
seashore
与えられた入力をグラフにしてみる(自己ループは無視)
S e
at
b y
考察
• 各文字 (a – z) に対してしりとりの最後になりうるかを判定したい
• 入次数と出次数に着目?
考察
• 各文字 (a – z) に対してしりとりの最後になりうるかを判定したい
• 入次数と出次数に着目?
(入次数) < (出次数)のとき
NG!
c
考察
• 各文字 (a – z) に対してしりとりの最後になりうるかを判定したい
• 入次数と出次数に着目?
(入次数) ≥ (出次数)のとき
OK?
c
考察
• 各文字 (a – z) に対してしりとりの最後になりうるかを判定したい
• 入次数と出次数に着目?
(入次数) ≥ (出次数)のとき
OK? 戻ってこれなかったらダメ
c
考察
• 各文字 (a – z) に対してしりとりの最後になりうるかを判定したい
下の図のように頂点を分解して
s から t への辺素なパスが出次数と同じになればOK!
辺素なパスの本数は容量 1 のグラフにおけるフロー値!
t s
実装例(C++)
問題(ICPC 国内予選 2009 E)
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1163&lang=jp
[問題概要]
青いカードが m 枚、赤いカードが n 枚あり、それぞれに1 ≤ 𝑥 ≤ 107
の整数が書かれている。赤のカードと青のカードから互いに素でない
ペアを選んで取り除く操作を行う。適切に操作を行った時、最大何組
のペアが取り除かれるか?
[制約]
1 ≤ 𝑚, 𝑛 ≤ 500
考察
引用 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1163&lang=jp
考察
• 最初に青の 2 と赤の 2 を取り除く
考察
考察
• 次に青の 6 と赤の 3 を取り除く
考察
考察
• 最後に青の 15 と 赤の 35 を取り除く
考察
• 答えは 3 !!
貪欲法?
取り除けるペアを見つけて、貪欲に取り除く
貪欲法?
例えば以下のようなとき、貪欲法ではだめなことがわかる。
Blue 2 3
Red 6 4
考察
• グラフに落とし込んで考察
考察
• 前処理で互いに素な頂点間に辺を張る
考察
• 作れるペアの最大値を求める問題 = 最大マッチング!!
考察
• 二部グラフの最大マッチングはフローを流すことで解けることが知ら
れている。(証明は後で)
アルゴリズム
架空の頂点 s t を追加
s
t
アルゴリズム
図のように
有向辺を張る
辺の
容量は1
s
t
アルゴリズム
s から t への最大フローが
最大マッチング
になる!
s
t
証明
• 復習 (最大マッチング)
マッチングが最大である  増加パスを持たない
フローによって得られたマッチングが増加パスを持たないことを示せ
ばよい
増加パスを持つことを仮定して矛盾を導く (背理法)
証明
増加パスを持つと仮定する。
以下の二つの部分構造のどちらかを持つ。
…
証明
増加パスを持つと仮定する。
以下の二つの部分構造のどちらかを持つ。
c
c
…
証明
• このマッチングを得るフローを考える
c
c
…
証明
• このマッチングを得るフローを考える
• 増加パス上の辺を反転させるようなフローを構成でき、フロー値を大
きくできる。
c
c
…
証明
• 最大フローであることに矛盾!
c
c
…
ソースコード (C++)
•
•
練習問題

最大流 (max flow)