MaxFlow

最大フロー問題 を解くライブラリです。

コンストラクタ

var graph = init_mf_graph[Cap](n:int)

n 頂点 $0$ 辺のグラフを作る。Capは容量の型。

制約

計算量

add_edge

graph.add_edge(src:int, dst:int, cap:Cap):int

fromからtoへ最大容量cap、流量 $0$ の辺を追加し、何番目に追加された辺かを返す。

制約

計算量

flow

(1) graph.flow(s:int, t:int):Cap
(2) graph.flow(s:int, t:int, flow_limit:Cap):Cap

制約

計算量

$m$ を追加された辺数として

min_cut

graph.min_cut(s:int):seq[bool]

長さ $n$ のvectorを返す。$i$ 番目の要素には、頂点 $s$ から $i$ へ残余グラフで到達可能なとき、またその時のみ true を返す。flow(s, t)をflow_limitなしでちょうど一回呼んだ後に呼ぶと、返り値は $s$, $t$ 間のmincutに対応します。詳細な挙動は Appendix を参照してください。

計算量

$m$ を追加された辺数として

get_edge / edges

edge_info[Cap] = object
  src, dst:int
  cap, flow:Cap

(1) graph.get_edge(i:int):edge_info[Cap]
(2) graph.edges():seq[edge_info[Cap]]

制約

計算量

$m$ を追加された辺数として

change_edge

graph.change_cap(i:int, new_cap:Cap, new_flow:Cap):void

$i$ 番目に変更された辺の容量、流量をnew_cap, new_flowに変更する。他の辺の容量、流量は変更しない。詳細は Appendix を参照してください

制約

計算量

使用例

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_d

include atcoder/header import atcoder/maxflow let n, m = nextInt() var grid = newSeqWith(n, nextString()) # generate (s -> even grid -> odd grid -> t) graph # grid(i, j) correspond to vertex (i * m + j) var g = initMFGraph[int](n * m + 2) let s = n * m t = n * m + 1; # s -> even / odd -> t for i in 0..<n: for j in 0..<m: if grid[i][j] == '#': continue let v = i * m + j if (i + j) mod 2 == 0: g.add_edge(s, v, 1) else: g.add_edge(v, t, 1) # even -> odd for i in 0..<n: for j in 0..<m: if (i + j) mod 2 == 1 or grid[i][j] == '#': continue let v0 = i * m + j if i != 0 and grid[i - 1][j] == '.': let v1 = (i - 1) * m + j g.add_edge(v0, v1, 1) if j != 0 and grid[i][j - 1] == '.': let v1 = i * m + (j - 1) g.add_edge(v0, v1, 1) if i + 1 < n and grid[i + 1][j] == '.': let v1 = (i + 1) * m + j g.add_edge(v0, v1, 1) if j + 1 < m and grid[i][j + 1] == '.': let v1 = i * m + (j + 1) g.add_edge(v0, v1, 1) echo g.flow(s, t) let edges = g.edges() for e in edges: if e.src == s or e.dst == t or e.flow == 0: continue let i0 = e.src div m j0 = e.src mod m i1 = e.dst div m j1 = e.dst mod m if i0 == i1 + 1: grid[i1][j1] = 'v'; grid[i0][j0] = '^' elif j0 == j1 + 1: grid[i1][j1] = '>'; grid[i0][j0] = '<' elif i0 == i1 - 1: grid[i0][j0] = 'v'; grid[i1][j1] = '^' else: grid[i0][j0] = '>'; grid[i1][j1] = '<' echo grid.join("\n")