SlideShare a Scribd company logo
1 of 67
Download to read offline
グラフネットワーク
~フロー & カット~
アルゴ研 D2 井上 祐馬
内容
• 最大流と最小カットの定義
• 最大流 - 最小カット定理
• 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic)
• 最小費用流とその解き方 (SSP)
• 全域最小カット・最大カット
内容
• 最大流と最小カットの定義
• 最大流 - 最小カット定理
• 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic)
• 最小費用流とその解き方 (SSP)
• 全域最小カット・最大カット
蟻本
蟻本
蟻本
not 蟻本
内容
• 最大流と最小カットの定義
• 最大流 - 最小カット定理
• 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic)
• 最小費用流とその解き方 (SSP)
• 全域最小カット・最大カット
ネットワークフロー
• 辺に容量制約がついた有向グラフ G = (V,E) を
考える
• 始点 (ソース) s から終点 (シンク) t へ、各辺の
容量制約を守って最大いくら t まで流せるか?
a
d
c
b
9
s t
10
8
4 3
4
3
6
ネットワークフロー
• 辺に容量制約がついた有向グラフ G = (V,E) を
考える
• 始点 (ソース) s から終点 (シンク) t へ、各辺の
容量制約を守って最大いくら t まで流せるか?
a
d
c
b
9
s t
10
8
4 3
4
3
6
10
4 3
1
3
88
2
合計14
ネットワークフロー
• もっと数学的な定義: G = (V,E) の s-t フローとは、
• 辺 e ∈ E に対し、容量関数 c(e)、流量関数 f(e)を
考える
• f(e) は以下の制約を満たす
• 0 ≤ f(e) ≤ c(e)
• v ∈ V  {s,t} について、Σe∈δ-(v) f(e) = Σe∈δ+(v) f(e)
• このとき、Σe∈δ+(s)f(e) (= Σe∈δ-(t)f(e)) を最大化せよ
入辺 出辺
グラフカット
• (重み付き)有向グラフ G = (V,E) を考える
• 頂点集合 V の任意の分割 S, VS に対し、S か
ら VS への辺の集合をカットセットと呼ぶ
a
d
c
b
9
s t
8
3
4
3
610
4
S
VS
グラフカット
• G の最小カットとは、任意のカットセットの
うち重み和が最小のもの
• 特に、与えられた s, t に対し、s ∈ S, t ∈ VS で
あるカットを s-t カットという
a
d
c
b
9
s t
10
8
4 3
4
3
6
合計14
内容
• 最大流と最小カットの定義
• 最大流 - 最小カット定理
• 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic)
• 最小費用流とその解き方 (SSP)
• 全域最小カット・最大カット
最大流・最小カット定理
• 辺に容量制約がついた有向グラフ G = (V,E) を
考える
• 最大 s-t フローの流量 = 最小 s-t カットの容量和
• 証明は後で
a
d
c
b
9
s t
10
8
4 3
4
3
6
10
4 3
1
3
88
2
合計14
a
d
c
b
9
s t
10
8
4 3
4
3
6
合計14
内容
• 最大流と最小カットの定義
• 最大流 - 最小カット定理
• 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic)
• 最小費用流とその解き方 (SSP)
• 全域最小カット・最大カット
間違った貪欲法
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
a
d
c
b
9
s t
10
8
4 3
4
3
6
間違った貪欲法
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
a
d
c
b
9
s t
10
8
4 3
4
3
6
4
4
4
間違った貪欲法
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
a
d
c
b
9
s t
10
8
4 3
4
3
6
10
4
4
66
間違った貪欲法
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
a
d
c
b
9
s t
10
8
4 3
4
3
6
10
4
4
66
3 3
間違った貪欲法
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
• 他のパスで流した方がよいところを勝手に先に
使ってしまうのでダメ
a
d
c
b
9
s t
10
8
4 3
4
3
6
10
4
4
66
3 3
a
d
c
b
9
s t
10
8
4 3
4
3
6
10
4 3
1
3
88
2
合計14合計13 <
Ford-Fulkerson のアルゴリズム
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
• 流れている容量分、逆辺を追加して押し戻せる
ようにする
• 逆辺込みのグラフを残余グラフという
a
d
c
b
9
s t
10
8
4 3
4
3
6
Ford-Fulkerson のアルゴリズム
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
• 流れている容量分、逆辺を追加して押し戻せる
ようにする
• 逆辺込みのグラフを残余グラフという
a
d
c
b
9
s t
6
8
4 3
0
3
2
4
44
Ford-Fulkerson のアルゴリズム
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
• 流れている容量分、逆辺を追加して押し戻せる
ようにする
• 逆辺込みのグラフを残余グラフという
a
d
c
b
3
s t
0
2
4 3
0
3
2
4
410
66
Ford-Fulkerson のアルゴリズム
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
• 流れている容量分、逆辺を追加して押し戻せる
ようにする
• 逆辺込みのグラフを残余グラフという
a
d
c
b
3
s t
0
2
1 0
0
3
2
4
410
66
3
3
Ford-Fulkerson のアルゴリズム
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
• 流れている容量分、逆辺を追加して押し戻せる
ようにする
• 逆辺込みのグラフを残余グラフという
a
d
c
b
2
s t
0
1
0 0
0
2
3
4
310
77
3
4
1
Ford-Fulkerson のアルゴリズム
• 容量が余っている辺からなる s-t パスがあれば
流せるだけ流す
• 流れている容量分、逆辺を追加して押し戻せる
ようにする
• 逆辺込みのグラフを残余グラフという
a
d
c
b
2
s t
0
1
0 0
0
2
3
4
310
77
3
4
1
最大流・最小カット定理の証明
• 証明は2つ
• フローの流量 ≤ カットの容量
• 最小カットの容量 ≤ 最大流の流量
a
d
c
b
9
s t
10
8
4 3
4
3
6
10
4 3
1
3
88
2
合計14
a
d
c
b
9
s t
10
8
4 3
4
3
6
合計14
1. フロー ≤ カット
• カットされていると s-t パスがないためフロー
が流せない

→ カットをやめても最大でカットの容量しか

  流せない
a
d
c
b
9
s t
10
8
4 3
4
3
6
2. 最小カット ≤ 最大流
• 最大流 残余グラフで s-t パスがない = カット
• 最大流の流量 = カットの容量 ≧ 最小カットの容量
• S から VS への辺の流量 = 容量
• VS から S への辺の流量 = 0 (= 逆辺容量も0)
a
d
c
b
2
s t
0
1
0 0
0
2
3
4
310
77
3
4
1
Ford-Fulkerson のアルゴリズム
• 残余グラフに s-t パスが存在する

→めいっぱい流した後、逆辺を張って

 残余グラフを更新
• 以上をパスがある限り繰り返す
• O(|F| |E|) : |F| = 最大流量、|E| = 辺数
a
d
c
b
9
s t
10
8
4 3
4
3
6
Ford-Fulkerson の実装 (グラフ構築)
struct edge{
int to, cap, rev;
edge(int t, int c, int r){
to = t; cap = c; rev = r;
}
};
void add_edge(int from, int to, int cap, vector< vector<edge> > &g){
g[from].push_back( edge(to,cap,g[to].size()) );
g[to].push_back( edge(from,0,g[from].size()-1) );
}
Ford-Fulkerson の実装 (本体)
int dfs(int v,int t, int f, vector< vector<edge> > &g, vector<int> &used){
if(v==t)return f;
used[v] = 1;
for(edge &e : g[v]){
if(!used[e.to] && e.cap>0){
int d = dfs(e.to,t,min(f,e.cap),g,used);
if(d>0){
e.cap -= d;
g[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int max_flow(int s, int t, vector< vector<edge> > g){
int flow = 0;
while(1){
vector<int> used(g.size(),0);
int f = dfs(s,t,INF,g,used);
if(f==0)return flow;
flow += f;
}
}
フローいろいろ
• 無向グラフのとき
• 双方向に辺を張ればよい
• 複数始点、複数終点がある
• 新たな始点、終点1つ用意して、それらにつなぐ
• 複数始点、複数終点かつ、始点・終点ペアが決まっている
• 多品種フローというNP完全問題、Ford-Fulkersonでは解けない
• 最小流量制約がある
• 蟻本を読もう!
• もっと高速に解きたい
• Dinic のアルゴリズム O(|E| |V|
2
) が知られている ← 蟻本を読もう!
• Push-relabel アルゴリズム O(|V|
3
) が知られている ← not 蟻本
内容
• 最大流と最小カットの定義
• 最大流 - 最小カット定理
• 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic)
• 最小費用流とその解き方 (SSP)
• 全域最小カット・最大カット
最小費用流
• 辺に容量制約、コストがついた有向グラフ G = (V,E) を考える
• 辺に流す流量1につき、辺についたコストがかかる
• 始点 (ソース) s から終点 (シンク) t へ、各辺の容量制約を

守って流量 f まで t へ流すとき、最小のコスト和はいくらか?
a
s t
容量5, コスト2
容量10, コスト5
容量2, コスト1
流量 f = 3 だけ流したい!
最小費用流
• 辺に容量制約、コストがついた有向グラフ G = (V,E) を考える
• 辺に流す流量1につき、辺についたコストがかかる
• 始点 (ソース) s から終点 (シンク) t へ、各辺の容量制約を

守って流量 f まで t へ流すとき、最小のコスト和はいくらか?
a
s t
容量5, コスト2
容量10, コスト5
容量2, コスト1
流量 f = 3 だけ流したい!
2 流す
1 流す コスト 2 (2+1) + 1 5 =11
最小!!!
SSP (Successive Shortest Path)
• 容量が余っている辺からなる s-t 最短路に流せ
るだけ流す
• 流れている容量分、逆辺を追加して押し戻せる
ようにする
• 逆辺のコストは正負を逆転する
a
s t
容量5, コスト2
容量10, コスト5
容量2, コスト1
流量 f = 3 だけ流したい!
最短路!
2まで流せる!
SSPの正当性
• コンテスタントがじゃぶじゃぶ最小費用流を
流したくなるような射幸心を りまくる証明
SSPの正当性
帰納法 : fx が x 流す時の最小費用流

→ 最短路にさらに1だけ流したfx+1は?
背理法: fx+1が最小費用流でないと仮定

→ もっとコストの小さいフロー f'x+1が存在
・f'x+1 - fx は s-t パスといくつかの閉路
・f'x+1 は fx+1 よりコストが小さい → 負の閉路が存在
→ fx に負の閉路があった → 補題に矛盾 → fx+1は最小費用流
・補題: 最小費用流の残余グラフは負の閉路を持たない
↑ 閉路に流しまくった方がコストが下がる
SSPのアルゴリズム
• 残余グラフに s-t パスが存在する

→ s-t 最短路を求めて目一杯流した後、

  逆辺を張って残余グラフを更新
• 以上をパスがある限り繰り返す
• 基本的に Ford-Fulkerson の dfs を最短路アルゴリズムに変えるだけ
• O(|F| ×最短路計算量) : |F| = 最大流量
• 逆辺が負値になるので Bellman-Ford (O(VE)) を使うのが基本
• ポテンシャル法の利用で Dijkstra (O(E+VlogV)) が使える ← 割愛
SSP (Bellman-Ford) の実装 (グラフの構築)
struct edge{
int to, cap, cost, rev;
edge(int t, int c, int v, int r){
to = t; cap = c; cost = v; rev = r;
}
};
void add_edge(int from, int to, int cap, int cost, vector< vector<edge> > &g){
g[from].push_back( edge(to,cap,cost,g[to].size()) );
g[to].push_back( edge(from,0,-cost,g[from].size()-1) );
}
SSP (Bellman-Ford) の実装 (最短路部分)
//Bellman-Ford based: O(FVE) , 入力: 隣接リスト
int min_cost_flow(int s, int t, int f, vector< vector<edge> > g){
int n = g.size(), res = 0;
while(f>0){
//最短路 (復元付き) を求める
vector<int> d(n,INF), pv(n), pe(n);
d[s] = 0;
bool update = true;
while(update){
update = false;
for(int v=0;v<n;v++){
for(int i=0;i<(int)g[v].size();i++){
edge &e = g[v][i];
if(e.cap>0 && d[e.to] > d[v] + e.cost){
d[e.to] = d[v] + e.cost;
pv[e.to] = v; pe[e.to] = i;
update = true;
}
}
}
}
SSP (Bellman-Ford) の実装 (グラフ更新部分)
// f 流すには容量が足りない
if(d[t]==INF)return -1;
//流せる流量の上限を求める
int x = f;
for(int v=t; v!=s; v=pv[v]){
x = min(x, g[pv[v]][pe[v]].cap);
}
f -= x;
res += x*d[t];
//実際に流す
for(int v=t; v!=s; v=pv[v]){
edge &e = g[pv[v]][pe[v]];
e.cap -= x;
g[e.to][e.rev].cap += x;
}
}
return res;
}
内容
• 最大流と最小カットの定義
• 最大流 - 最小カット定理
• 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic)
• 最小費用流とその解き方 (Primal-Dual)
• 全域最小カット・最大カット
全域最小/最大カット
• 正の重み付き無向グラフ G = (V,E) を考える
• 任意の非空集合 S ⊂ V におけるカットのうち、重み
和最小 (最大) のものを全域最小 (最大) カットという
• s, t の縛りがない
a b
c
1
d
2
4
2
6
重み和 5
全域最小/最大カット
• 残念なお知らせ:

(全域) 最大カットはNP完全
• 朗報:

全域最小カットは O(VE + V2logV) で解ける
a b
c
1
d
2
4
2
6
重み和 5
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点1つをリスト L に入れる
2. まだ L に入れてない頂点がある限り、
・ L の頂点との辺重み和が最大の頂点を L に加える
3. L|V| と他の頂点との間の辺重み和を W とおく
4. L|V| と L|V|-1 を1つの頂点にまとめて G' とする
5. min( W, MinCostCut( G' ) ) が答え
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( )
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a )
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a )
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a, c )
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a, c )
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a, c, b )
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a, c, b )
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a, c, b, d )
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a, c, b, d )
W = 6
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
a b
c
1
d
2
4
2
6
L = ( a, c, b, d )
W = 6
a
bd
c
3
2
6
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
Wd = 6
a
bd
c
3
2
6
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
Wd = 6
a
bd
c
3
2
6
L = ( a, c, bd )
Wbd = 5
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
Wd = 6
a
bd
c
3
2
6
L = ( a, c, bd )
Wbd = 5
a
bcd
8
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
Wd = 6
L = ( a, bcd)
Wbd = 5
a
bcd
8 Wa = 8
Stoer-Wagner のアルゴリズム
MinCostCut (G = (V, E) ):
1. 適当な頂点をリスト L に入れる
2. L に入れてない頂点がある限り、
・ L との辺重み和が最大の頂点を

   L に加える
3. L|V| と他の頂点との辺重み和を W
4. L|V| と L|V|-1 を1つにまとめて G'
5. min( W, MinCostCut( G' ) ) が答え
Wd = 6
L = ( a, bcd)
Wbd = 5
a
bcd
8 Wa = 8
最小全域カット = 5
Stoer-Wagner の正当性
• 最大隣接順序 (Maximum Adjacent Order) で頂点
を並べた最後の2頂点を s, t とする
• 以下の2つの定理が成り立てば正しい
1. t から他の全頂点への辺和は最小 s-t カットに
等しい
2. G の最小カットは、G'の最小カットか最小 s-t
カットかのいずれか
Stoer-Wagner の正当性
1. t から他の全頂点への辺和は最小 s-t カットに等しい
• 任意の s-t カット C について、w(At,t) ≤ w(Ct) を言え
ばよい
• Av : MA Order で v より前の頂点集合
• w(A,v) : Aとvの間の辺の重み和
• Cv : Cのうち、Av ∪ {v} 間の辺のみの集合
• w(C) : 辺集合 C に含まれる辺の重み和
Stoer-Wagner の正当性
1. t から他の全頂点への辺和は最小 s-t カットに等しい
• active な頂点に関する帰納法
• v が active : カット C 中で v と1つ前の頂点が

違う集合に分けられている
• vの直前の active な頂点u が w(Au,u) ≤ w(Cu) と仮定

→ w(Av,v) ≤ w(Cv) が言えればよい
vu ...... ...
active
Stoer-Wagner の正当性
1. t から他の全頂点への辺和は最小 s-t カットに等しい
• 帰納法 : w(Av,v) ≤ w(Cv) を言いたい
• w(Av,v) = w(Au,v) + w(AvAu,v) ← 集合分けただけ

≤ w(Au,u) + w(AvAu,v) ← MA Order

≤ w(Cu) + w(AvAu,v) ← 帰納法仮定

≤ w(Cv) ← 下図
v
u ......
w(Cu)
w(AvAu,v)
足されてない
Stoer-Wagner の正当性
2. G の最小カットは、G'の最小カットか最小 s-t
 カットかのいずれか
• まあ自明
• G'の最小カット = s と t を分けない最小カット
• つまり、最小カットは s と t を分ける最小カットか
分けない最小カットかのいずれか、と言ってるだけ
Stoer-Wagnerの計算量
• MinCostCut の呼び出しはちょうど|V|-1回
• 計算量は MA 順序の計算と頂点縮約に依存
• MA 順序: ダイクストラっぽくできる

→ O(|V|2
) か普通のヒープでO(|E|log|V|) 

(フィボナッチヒープを使って O(|E| + |V|log|V|) )
• 縮約: 適当にやってもO(|E|)
• 全体で O(V3
) or O(|V||E| log|V|)
Stoer-Wagner の実装
//入力: n×n隣接行列
int global_min_cut(vector< vector<int> > g){
int n = g.size(), res = INF;
vector<int> redV(n);
rep(i,n)redV[i] = i;
for(int rem=n;rem>1;rem--){
//calc MA order
int u=0, v=0, cut=0;
vector<int> w(rem,0);
for(int i=0;i<rem;i++){
u = v; v = max_element(w.begin(), w.end()) - w.begin();
cut = w[v]; w[v] = -1;
for(int p=0;p<rem;p++){
if(w[p]>=0)w[p] += g[redV[v]][redV[p]];
}
}
//merge graph
rep(i,rem){
g[redV[u]][redV[i]] += g[redV[v]][redV[i]];
g[redV[i]][redV[u]] += g[redV[i]][redV[v]];
}
redV.erase(redV.begin() + v);
//update min_cut
res = min(res, cut);
}
return res;
}
まとめ
• グラフネットワークに対する問題とアルゴリズム
• 最大流 = 最小カット: Ford-Fulkerson O(FE)
• 最小費用流 : SSP O(FVE)
• 全域最小カット: Stoer-Wagner O(V3
) or O(VElogV)
• まだまだいろいろあります (そのうち)

More Related Content

What's hot

AtCoder Regular Contest 031 解説
AtCoder Regular Contest 031 解説AtCoder Regular Contest 031 解説
AtCoder Regular Contest 031 解説AtCoder Inc.
 
ユークリッド最小全域木
ユークリッド最小全域木ユークリッド最小全域木
ユークリッド最小全域木理玖 川崎
 
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~Takuya Akiba
 
AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説AtCoder Inc.
 
AtCoder Beginner Contest 021 解説
AtCoder Beginner Contest 021 解説AtCoder Beginner Contest 021 解説
AtCoder Beginner Contest 021 解説AtCoder Inc.
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門Yoichi Iwata
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法Takuya Akiba
 
AtCoder Beginner Contest 007 解説
AtCoder Beginner Contest 007 解説AtCoder Beginner Contest 007 解説
AtCoder Beginner Contest 007 解説AtCoder Inc.
 
AtCoder Regular Contest 046
AtCoder Regular Contest 046AtCoder Regular Contest 046
AtCoder Regular Contest 046AtCoder Inc.
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~Yuma Inoue
 
AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Inc.
 
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方Kensuke Otsuki
 
色々なダイクストラ高速化
色々なダイクストラ高速化色々なダイクストラ高速化
色々なダイクストラ高速化yosupo
 
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムプログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムTakuya Akiba
 

What's hot (20)

AtCoder Regular Contest 031 解説
AtCoder Regular Contest 031 解説AtCoder Regular Contest 031 解説
AtCoder Regular Contest 031 解説
 
ユークリッド最小全域木
ユークリッド最小全域木ユークリッド最小全域木
ユークリッド最小全域木
 
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
 
AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説
 
AtCoder Beginner Contest 021 解説
AtCoder Beginner Contest 021 解説AtCoder Beginner Contest 021 解説
AtCoder Beginner Contest 021 解説
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
 
Binary indexed tree
Binary indexed treeBinary indexed tree
Binary indexed tree
 
動的計画法を極める!
動的計画法を極める!動的計画法を極める!
動的計画法を極める!
 
Convex Hull Trick
Convex Hull TrickConvex Hull Trick
Convex Hull Trick
 
AtCoder Beginner Contest 007 解説
AtCoder Beginner Contest 007 解説AtCoder Beginner Contest 007 解説
AtCoder Beginner Contest 007 解説
 
abc032
abc032abc032
abc032
 
AtCoder Regular Contest 046
AtCoder Regular Contest 046AtCoder Regular Contest 046
AtCoder Regular Contest 046
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~
 
AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説
 
Rolling hash
Rolling hashRolling hash
Rolling hash
 
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
 
RMQ クエリ処理
RMQ クエリ処理RMQ クエリ処理
RMQ クエリ処理
 
色々なダイクストラ高速化
色々なダイクストラ高速化色々なダイクストラ高速化
色々なダイクストラ高速化
 
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムプログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
 

More from HCPC: 北海道大学競技プログラミングサークル

More from HCPC: 北海道大学競技プログラミングサークル (20)

写像 12 相
写像 12 相写像 12 相
写像 12 相
 
ACPC 2017 Day3 F: 掛け算は楽しい
ACPC 2017 Day3 F: 掛け算は楽しいACPC 2017 Day3 F: 掛け算は楽しい
ACPC 2017 Day3 F: 掛け算は楽しい
 
ACPC 2017 Day3 D: 優柔不断
ACPC 2017 Day3 D: 優柔不断ACPC 2017 Day3 D: 優柔不断
ACPC 2017 Day3 D: 優柔不断
 
ACPC 2019 Day3 G: Restricted DFS
ACPC 2019 Day3 G: Restricted DFSACPC 2019 Day3 G: Restricted DFS
ACPC 2019 Day3 G: Restricted DFS
 
ACPC 2019 Day3 F: 部分文字列分解
ACPC 2019 Day3 F: 部分文字列分解ACPC 2019 Day3 F: 部分文字列分解
ACPC 2019 Day3 F: 部分文字列分解
 
ACPC 2019 Day3 E: 総和の切り取り
ACPC 2019 Day3 E: 総和の切り取りACPC 2019 Day3 E: 総和の切り取り
ACPC 2019 Day3 E: 総和の切り取り
 
ACPC 2019 Day3 B: パフェ
ACPC 2019 Day3 B: パフェACPC 2019 Day3 B: パフェ
ACPC 2019 Day3 B: パフェ
 
ACPC 2019 Day3 A: 間違い探し
ACPC 2019 Day3 A: 間違い探しACPC 2019 Day3 A: 間違い探し
ACPC 2019 Day3 A: 間違い探し
 
HUPC 2019 Day2 G: 木
HUPC 2019 Day2 G: 木HUPC 2019 Day2 G: 木
HUPC 2019 Day2 G: 木
 
HUPC 2019 Day2 E: ジャム
HUPC 2019 Day2 E: ジャムHUPC 2019 Day2 E: ジャム
HUPC 2019 Day2 E: ジャム
 
HUPC 2019 Day2 H: Revenge of UMG
HUPC 2019 Day2 H: Revenge of UMGHUPC 2019 Day2 H: Revenge of UMG
HUPC 2019 Day2 H: Revenge of UMG
 
HUPC 2019 Day2 F: MOD Rush
HUPC 2019 Day2 F: MOD RushHUPC 2019 Day2 F: MOD Rush
HUPC 2019 Day2 F: MOD Rush
 
HUPC 2019 Day2 C: 串刺し
HUPC 2019 Day2 C: 串刺しHUPC 2019 Day2 C: 串刺し
HUPC 2019 Day2 C: 串刺し
 
HUPC 2019 Day1 F: グリッドの番号
HUPC 2019 Day1 F: グリッドの番号HUPC 2019 Day1 F: グリッドの番号
HUPC 2019 Day1 F: グリッドの番号
 
HUPC 2019 Day1 E: 最短経路の復元
HUPC 2019 Day1 E: 最短経路の復元HUPC 2019 Day1 E: 最短経路の復元
HUPC 2019 Day1 E: 最短経路の復元
 
HUPC 2019 Day1 D: 貪欲が最適?
HUPC 2019 Day1 D: 貪欲が最適?HUPC 2019 Day1 D: 貪欲が最適?
HUPC 2019 Day1 D: 貪欲が最適?
 
HUPC 2019 Day1 C: 短絡評価
HUPC 2019 Day1 C: 短絡評価HUPC 2019 Day1 C: 短絡評価
HUPC 2019 Day1 C: 短絡評価
 
HUPC 2019 Day1 B: 自身の 2 倍
HUPC 2019 Day1 B: 自身の 2 倍HUPC 2019 Day1 B: 自身の 2 倍
HUPC 2019 Day1 B: 自身の 2 倍
 
HUPC 2019 Day1 A: four tea
HUPC 2019 Day1 A: four teaHUPC 2019 Day1 A: four tea
HUPC 2019 Day1 A: four tea
 
プログラミングコンテスト基礎テクニック
プログラミングコンテスト基礎テクニックプログラミングコンテスト基礎テクニック
プログラミングコンテスト基礎テクニック
 

Recently uploaded

Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 

Recently uploaded (9)

Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 

グラフネットワーク〜フロー&カット〜

  • 2. 内容 • 最大流と最小カットの定義 • 最大流 - 最小カット定理 • 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic) • 最小費用流とその解き方 (SSP) • 全域最小カット・最大カット
  • 3. 内容 • 最大流と最小カットの定義 • 最大流 - 最小カット定理 • 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic) • 最小費用流とその解き方 (SSP) • 全域最小カット・最大カット 蟻本 蟻本 蟻本 not 蟻本
  • 4. 内容 • 最大流と最小カットの定義 • 最大流 - 最小カット定理 • 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic) • 最小費用流とその解き方 (SSP) • 全域最小カット・最大カット
  • 5. ネットワークフロー • 辺に容量制約がついた有向グラフ G = (V,E) を 考える • 始点 (ソース) s から終点 (シンク) t へ、各辺の 容量制約を守って最大いくら t まで流せるか? a d c b 9 s t 10 8 4 3 4 3 6
  • 6. ネットワークフロー • 辺に容量制約がついた有向グラフ G = (V,E) を 考える • 始点 (ソース) s から終点 (シンク) t へ、各辺の 容量制約を守って最大いくら t まで流せるか? a d c b 9 s t 10 8 4 3 4 3 6 10 4 3 1 3 88 2 合計14
  • 7. ネットワークフロー • もっと数学的な定義: G = (V,E) の s-t フローとは、 • 辺 e ∈ E に対し、容量関数 c(e)、流量関数 f(e)を 考える • f(e) は以下の制約を満たす • 0 ≤ f(e) ≤ c(e) • v ∈ V {s,t} について、Σe∈δ-(v) f(e) = Σe∈δ+(v) f(e) • このとき、Σe∈δ+(s)f(e) (= Σe∈δ-(t)f(e)) を最大化せよ 入辺 出辺
  • 8. グラフカット • (重み付き)有向グラフ G = (V,E) を考える • 頂点集合 V の任意の分割 S, VS に対し、S か ら VS への辺の集合をカットセットと呼ぶ a d c b 9 s t 8 3 4 3 610 4 S VS
  • 9. グラフカット • G の最小カットとは、任意のカットセットの うち重み和が最小のもの • 特に、与えられた s, t に対し、s ∈ S, t ∈ VS で あるカットを s-t カットという a d c b 9 s t 10 8 4 3 4 3 6 合計14
  • 10. 内容 • 最大流と最小カットの定義 • 最大流 - 最小カット定理 • 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic) • 最小費用流とその解き方 (SSP) • 全域最小カット・最大カット
  • 11. 最大流・最小カット定理 • 辺に容量制約がついた有向グラフ G = (V,E) を 考える • 最大 s-t フローの流量 = 最小 s-t カットの容量和 • 証明は後で a d c b 9 s t 10 8 4 3 4 3 6 10 4 3 1 3 88 2 合計14 a d c b 9 s t 10 8 4 3 4 3 6 合計14
  • 12. 内容 • 最大流と最小カットの定義 • 最大流 - 最小カット定理 • 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic) • 最小費用流とその解き方 (SSP) • 全域最小カット・最大カット
  • 13. 間違った貪欲法 • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す a d c b 9 s t 10 8 4 3 4 3 6
  • 14. 間違った貪欲法 • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す a d c b 9 s t 10 8 4 3 4 3 6 4 4 4
  • 15. 間違った貪欲法 • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す a d c b 9 s t 10 8 4 3 4 3 6 10 4 4 66
  • 16. 間違った貪欲法 • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す a d c b 9 s t 10 8 4 3 4 3 6 10 4 4 66 3 3
  • 17. 間違った貪欲法 • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す • 他のパスで流した方がよいところを勝手に先に 使ってしまうのでダメ a d c b 9 s t 10 8 4 3 4 3 6 10 4 4 66 3 3 a d c b 9 s t 10 8 4 3 4 3 6 10 4 3 1 3 88 2 合計14合計13 <
  • 18. Ford-Fulkerson のアルゴリズム • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す • 流れている容量分、逆辺を追加して押し戻せる ようにする • 逆辺込みのグラフを残余グラフという a d c b 9 s t 10 8 4 3 4 3 6
  • 19. Ford-Fulkerson のアルゴリズム • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す • 流れている容量分、逆辺を追加して押し戻せる ようにする • 逆辺込みのグラフを残余グラフという a d c b 9 s t 6 8 4 3 0 3 2 4 44
  • 20. Ford-Fulkerson のアルゴリズム • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す • 流れている容量分、逆辺を追加して押し戻せる ようにする • 逆辺込みのグラフを残余グラフという a d c b 3 s t 0 2 4 3 0 3 2 4 410 66
  • 21. Ford-Fulkerson のアルゴリズム • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す • 流れている容量分、逆辺を追加して押し戻せる ようにする • 逆辺込みのグラフを残余グラフという a d c b 3 s t 0 2 1 0 0 3 2 4 410 66 3 3
  • 22. Ford-Fulkerson のアルゴリズム • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す • 流れている容量分、逆辺を追加して押し戻せる ようにする • 逆辺込みのグラフを残余グラフという a d c b 2 s t 0 1 0 0 0 2 3 4 310 77 3 4 1
  • 23. Ford-Fulkerson のアルゴリズム • 容量が余っている辺からなる s-t パスがあれば 流せるだけ流す • 流れている容量分、逆辺を追加して押し戻せる ようにする • 逆辺込みのグラフを残余グラフという a d c b 2 s t 0 1 0 0 0 2 3 4 310 77 3 4 1
  • 24. 最大流・最小カット定理の証明 • 証明は2つ • フローの流量 ≤ カットの容量 • 最小カットの容量 ≤ 最大流の流量 a d c b 9 s t 10 8 4 3 4 3 6 10 4 3 1 3 88 2 合計14 a d c b 9 s t 10 8 4 3 4 3 6 合計14
  • 25. 1. フロー ≤ カット • カットされていると s-t パスがないためフロー が流せない
 → カットをやめても最大でカットの容量しか
   流せない a d c b 9 s t 10 8 4 3 4 3 6
  • 26. 2. 最小カット ≤ 最大流 • 最大流 残余グラフで s-t パスがない = カット • 最大流の流量 = カットの容量 ≧ 最小カットの容量 • S から VS への辺の流量 = 容量 • VS から S への辺の流量 = 0 (= 逆辺容量も0) a d c b 2 s t 0 1 0 0 0 2 3 4 310 77 3 4 1
  • 27. Ford-Fulkerson のアルゴリズム • 残余グラフに s-t パスが存在する
 →めいっぱい流した後、逆辺を張って
  残余グラフを更新 • 以上をパスがある限り繰り返す • O(|F| |E|) : |F| = 最大流量、|E| = 辺数 a d c b 9 s t 10 8 4 3 4 3 6
  • 28. Ford-Fulkerson の実装 (グラフ構築) struct edge{ int to, cap, rev; edge(int t, int c, int r){ to = t; cap = c; rev = r; } }; void add_edge(int from, int to, int cap, vector< vector<edge> > &g){ g[from].push_back( edge(to,cap,g[to].size()) ); g[to].push_back( edge(from,0,g[from].size()-1) ); }
  • 29. Ford-Fulkerson の実装 (本体) int dfs(int v,int t, int f, vector< vector<edge> > &g, vector<int> &used){ if(v==t)return f; used[v] = 1; for(edge &e : g[v]){ if(!used[e.to] && e.cap>0){ int d = dfs(e.to,t,min(f,e.cap),g,used); if(d>0){ e.cap -= d; g[e.to][e.rev].cap += d; return d; } } } return 0; } int max_flow(int s, int t, vector< vector<edge> > g){ int flow = 0; while(1){ vector<int> used(g.size(),0); int f = dfs(s,t,INF,g,used); if(f==0)return flow; flow += f; } }
  • 30. フローいろいろ • 無向グラフのとき • 双方向に辺を張ればよい • 複数始点、複数終点がある • 新たな始点、終点1つ用意して、それらにつなぐ • 複数始点、複数終点かつ、始点・終点ペアが決まっている • 多品種フローというNP完全問題、Ford-Fulkersonでは解けない • 最小流量制約がある • 蟻本を読もう! • もっと高速に解きたい • Dinic のアルゴリズム O(|E| |V| 2 ) が知られている ← 蟻本を読もう! • Push-relabel アルゴリズム O(|V| 3 ) が知られている ← not 蟻本
  • 31. 内容 • 最大流と最小カットの定義 • 最大流 - 最小カット定理 • 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic) • 最小費用流とその解き方 (SSP) • 全域最小カット・最大カット
  • 32. 最小費用流 • 辺に容量制約、コストがついた有向グラフ G = (V,E) を考える • 辺に流す流量1につき、辺についたコストがかかる • 始点 (ソース) s から終点 (シンク) t へ、各辺の容量制約を
 守って流量 f まで t へ流すとき、最小のコスト和はいくらか? a s t 容量5, コスト2 容量10, コスト5 容量2, コスト1 流量 f = 3 だけ流したい!
  • 33. 最小費用流 • 辺に容量制約、コストがついた有向グラフ G = (V,E) を考える • 辺に流す流量1につき、辺についたコストがかかる • 始点 (ソース) s から終点 (シンク) t へ、各辺の容量制約を
 守って流量 f まで t へ流すとき、最小のコスト和はいくらか? a s t 容量5, コスト2 容量10, コスト5 容量2, コスト1 流量 f = 3 だけ流したい! 2 流す 1 流す コスト 2 (2+1) + 1 5 =11 最小!!!
  • 34. SSP (Successive Shortest Path) • 容量が余っている辺からなる s-t 最短路に流せ るだけ流す • 流れている容量分、逆辺を追加して押し戻せる ようにする • 逆辺のコストは正負を逆転する a s t 容量5, コスト2 容量10, コスト5 容量2, コスト1 流量 f = 3 だけ流したい! 最短路! 2まで流せる!
  • 36. SSPの正当性 帰納法 : fx が x 流す時の最小費用流
 → 最短路にさらに1だけ流したfx+1は? 背理法: fx+1が最小費用流でないと仮定
 → もっとコストの小さいフロー f'x+1が存在 ・f'x+1 - fx は s-t パスといくつかの閉路 ・f'x+1 は fx+1 よりコストが小さい → 負の閉路が存在 → fx に負の閉路があった → 補題に矛盾 → fx+1は最小費用流 ・補題: 最小費用流の残余グラフは負の閉路を持たない ↑ 閉路に流しまくった方がコストが下がる
  • 37. SSPのアルゴリズム • 残余グラフに s-t パスが存在する
 → s-t 最短路を求めて目一杯流した後、
   逆辺を張って残余グラフを更新 • 以上をパスがある限り繰り返す • 基本的に Ford-Fulkerson の dfs を最短路アルゴリズムに変えるだけ • O(|F| ×最短路計算量) : |F| = 最大流量 • 逆辺が負値になるので Bellman-Ford (O(VE)) を使うのが基本 • ポテンシャル法の利用で Dijkstra (O(E+VlogV)) が使える ← 割愛
  • 38. SSP (Bellman-Ford) の実装 (グラフの構築) struct edge{ int to, cap, cost, rev; edge(int t, int c, int v, int r){ to = t; cap = c; cost = v; rev = r; } }; void add_edge(int from, int to, int cap, int cost, vector< vector<edge> > &g){ g[from].push_back( edge(to,cap,cost,g[to].size()) ); g[to].push_back( edge(from,0,-cost,g[from].size()-1) ); }
  • 39. SSP (Bellman-Ford) の実装 (最短路部分) //Bellman-Ford based: O(FVE) , 入力: 隣接リスト int min_cost_flow(int s, int t, int f, vector< vector<edge> > g){ int n = g.size(), res = 0; while(f>0){ //最短路 (復元付き) を求める vector<int> d(n,INF), pv(n), pe(n); d[s] = 0; bool update = true; while(update){ update = false; for(int v=0;v<n;v++){ for(int i=0;i<(int)g[v].size();i++){ edge &e = g[v][i]; if(e.cap>0 && d[e.to] > d[v] + e.cost){ d[e.to] = d[v] + e.cost; pv[e.to] = v; pe[e.to] = i; update = true; } } } }
  • 40. SSP (Bellman-Ford) の実装 (グラフ更新部分) // f 流すには容量が足りない if(d[t]==INF)return -1; //流せる流量の上限を求める int x = f; for(int v=t; v!=s; v=pv[v]){ x = min(x, g[pv[v]][pe[v]].cap); } f -= x; res += x*d[t]; //実際に流す for(int v=t; v!=s; v=pv[v]){ edge &e = g[pv[v]][pe[v]]; e.cap -= x; g[e.to][e.rev].cap += x; } } return res; }
  • 41. 内容 • 最大流と最小カットの定義 • 最大流 - 最小カット定理 • 最大流を求めるアルゴリズム (Ford-Fulkerson, Dinic) • 最小費用流とその解き方 (Primal-Dual) • 全域最小カット・最大カット
  • 42. 全域最小/最大カット • 正の重み付き無向グラフ G = (V,E) を考える • 任意の非空集合 S ⊂ V におけるカットのうち、重み 和最小 (最大) のものを全域最小 (最大) カットという • s, t の縛りがない a b c 1 d 2 4 2 6 重み和 5
  • 43. 全域最小/最大カット • 残念なお知らせ:
 (全域) 最大カットはNP完全 • 朗報:
 全域最小カットは O(VE + V2logV) で解ける a b c 1 d 2 4 2 6 重み和 5
  • 44. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点1つをリスト L に入れる 2. まだ L に入れてない頂点がある限り、 ・ L の頂点との辺重み和が最大の頂点を L に加える 3. L|V| と他の頂点との間の辺重み和を W とおく 4. L|V| と L|V|-1 を1つの頂点にまとめて G' とする 5. min( W, MinCostCut( G' ) ) が答え
  • 45. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( )
  • 46. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a )
  • 47. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a )
  • 48. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a, c )
  • 49. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a, c )
  • 50. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a, c, b )
  • 51. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a, c, b )
  • 52. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a, c, b, d )
  • 53. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a, c, b, d ) W = 6
  • 54. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え a b c 1 d 2 4 2 6 L = ( a, c, b, d ) W = 6 a bd c 3 2 6
  • 55. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え Wd = 6 a bd c 3 2 6
  • 56. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え Wd = 6 a bd c 3 2 6 L = ( a, c, bd ) Wbd = 5
  • 57. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え Wd = 6 a bd c 3 2 6 L = ( a, c, bd ) Wbd = 5 a bcd 8
  • 58. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え Wd = 6 L = ( a, bcd) Wbd = 5 a bcd 8 Wa = 8
  • 59. Stoer-Wagner のアルゴリズム MinCostCut (G = (V, E) ): 1. 適当な頂点をリスト L に入れる 2. L に入れてない頂点がある限り、 ・ L との辺重み和が最大の頂点を
    L に加える 3. L|V| と他の頂点との辺重み和を W 4. L|V| と L|V|-1 を1つにまとめて G' 5. min( W, MinCostCut( G' ) ) が答え Wd = 6 L = ( a, bcd) Wbd = 5 a bcd 8 Wa = 8 最小全域カット = 5
  • 60. Stoer-Wagner の正当性 • 最大隣接順序 (Maximum Adjacent Order) で頂点 を並べた最後の2頂点を s, t とする • 以下の2つの定理が成り立てば正しい 1. t から他の全頂点への辺和は最小 s-t カットに 等しい 2. G の最小カットは、G'の最小カットか最小 s-t カットかのいずれか
  • 61. Stoer-Wagner の正当性 1. t から他の全頂点への辺和は最小 s-t カットに等しい • 任意の s-t カット C について、w(At,t) ≤ w(Ct) を言え ばよい • Av : MA Order で v より前の頂点集合 • w(A,v) : Aとvの間の辺の重み和 • Cv : Cのうち、Av ∪ {v} 間の辺のみの集合 • w(C) : 辺集合 C に含まれる辺の重み和
  • 62. Stoer-Wagner の正当性 1. t から他の全頂点への辺和は最小 s-t カットに等しい • active な頂点に関する帰納法 • v が active : カット C 中で v と1つ前の頂点が
 違う集合に分けられている • vの直前の active な頂点u が w(Au,u) ≤ w(Cu) と仮定
 → w(Av,v) ≤ w(Cv) が言えればよい vu ...... ... active
  • 63. Stoer-Wagner の正当性 1. t から他の全頂点への辺和は最小 s-t カットに等しい • 帰納法 : w(Av,v) ≤ w(Cv) を言いたい • w(Av,v) = w(Au,v) + w(AvAu,v) ← 集合分けただけ
 ≤ w(Au,u) + w(AvAu,v) ← MA Order
 ≤ w(Cu) + w(AvAu,v) ← 帰納法仮定
 ≤ w(Cv) ← 下図 v u ...... w(Cu) w(AvAu,v) 足されてない
  • 64. Stoer-Wagner の正当性 2. G の最小カットは、G'の最小カットか最小 s-t  カットかのいずれか • まあ自明 • G'の最小カット = s と t を分けない最小カット • つまり、最小カットは s と t を分ける最小カットか 分けない最小カットかのいずれか、と言ってるだけ
  • 65. Stoer-Wagnerの計算量 • MinCostCut の呼び出しはちょうど|V|-1回 • 計算量は MA 順序の計算と頂点縮約に依存 • MA 順序: ダイクストラっぽくできる
 → O(|V|2 ) か普通のヒープでO(|E|log|V|) 
 (フィボナッチヒープを使って O(|E| + |V|log|V|) ) • 縮約: 適当にやってもO(|E|) • 全体で O(V3 ) or O(|V||E| log|V|)
  • 66. Stoer-Wagner の実装 //入力: n×n隣接行列 int global_min_cut(vector< vector<int> > g){ int n = g.size(), res = INF; vector<int> redV(n); rep(i,n)redV[i] = i; for(int rem=n;rem>1;rem--){ //calc MA order int u=0, v=0, cut=0; vector<int> w(rem,0); for(int i=0;i<rem;i++){ u = v; v = max_element(w.begin(), w.end()) - w.begin(); cut = w[v]; w[v] = -1; for(int p=0;p<rem;p++){ if(w[p]>=0)w[p] += g[redV[v]][redV[p]]; } } //merge graph rep(i,rem){ g[redV[u]][redV[i]] += g[redV[v]][redV[i]]; g[redV[i]][redV[u]] += g[redV[i]][redV[v]]; } redV.erase(redV.begin() + v); //update min_cut res = min(res, cut); } return res; }
  • 67. まとめ • グラフネットワークに対する問題とアルゴリズム • 最大流 = 最小カット: Ford-Fulkerson O(FE) • 最小費用流 : SSP O(FVE) • 全域最小カット: Stoer-Wagner O(V3 ) or O(VElogV) • まだまだいろいろあります (そのうち)