SlideShare uma empresa Scribd logo
1 de 67
Baixar para ler 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)
• まだまだいろいろあります (そのうち)

Mais conteúdo relacionado

Mais procurados

プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムプログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムTakuya Akiba
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門Yoichi Iwata
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法Takuya Akiba
 
AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Inc.
 
AtCoder Beginner Contest 035 解説
AtCoder Beginner Contest 035 解説AtCoder Beginner Contest 035 解説
AtCoder Beginner Contest 035 解説AtCoder Inc.
 
様々な全域木問題
様々な全域木問題様々な全域木問題
様々な全域木問題tmaehara
 
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~Takuya Akiba
 
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~Takuya Akiba
 
AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Inc.
 
AtCoder Regular Contest 033 解説
AtCoder Regular Contest 033 解説AtCoder Regular Contest 033 解説
AtCoder Regular Contest 033 解説AtCoder Inc.
 
AtCoder Beginner Contest 002 解説
AtCoder Beginner Contest 002 解説AtCoder Beginner Contest 002 解説
AtCoder Beginner Contest 002 解説AtCoder Inc.
 
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話Nagisa Eto
 
指数時間アルゴリズムの最先端
指数時間アルゴリズムの最先端指数時間アルゴリズムの最先端
指数時間アルゴリズムの最先端Yoichi Iwata
 

Mais procurados (20)

プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムプログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門
 
Binary indexed tree
Binary indexed treeBinary indexed tree
Binary indexed tree
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
 
RMQ クエリ処理
RMQ クエリ処理RMQ クエリ処理
RMQ クエリ処理
 
AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説
 
arc047
arc047arc047
arc047
 
AtCoder Beginner Contest 035 解説
AtCoder Beginner Contest 035 解説AtCoder Beginner Contest 035 解説
AtCoder Beginner Contest 035 解説
 
様々な全域木問題
様々な全域木問題様々な全域木問題
様々な全域木問題
 
WUPC2012
WUPC2012WUPC2012
WUPC2012
 
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
 
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
 
AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説
 
AtCoder Regular Contest 033 解説
AtCoder Regular Contest 033 解説AtCoder Regular Contest 033 解説
AtCoder Regular Contest 033 解説
 
AtCoder Beginner Contest 002 解説
AtCoder Beginner Contest 002 解説AtCoder Beginner Contest 002 解説
AtCoder Beginner Contest 002 解説
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話
 
abc032
abc032abc032
abc032
 
Topological sort
Topological sortTopological sort
Topological sort
 
指数時間アルゴリズムの最先端
指数時間アルゴリズムの最先端指数時間アルゴリズムの最先端
指数時間アルゴリズムの最先端
 

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

Mais de 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
 
Convex Hull Trick
Convex Hull TrickConvex Hull Trick
Convex Hull Trick
 

Último

自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 

Último (8)

自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 

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

  • 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) • まだまだいろいろあります (そのうち)