# verification-helper: PROBLEM https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_6_A require "../../src/nglib/graph/max_flow" n, m = read_line.split.map &.to_i graph = NgLib::MaxFlowGraph(Int32).new(n) m.times do u, v, c = read_line.split.map &.to_i graph.add_edge(u, v, c) end ans = graph.flow(0, n - 1) puts ans
# verification-helper: PROBLEM https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_6_A # require "../../src/nglib/graph/max_flow" module NgLib class MaxFlowGraph(Cap) class Edge(T) getter to : Int32 getter rev : Int32 property cap : T def initialize(@to, @rev, @cap) end end getter size : Int32 @graph : Array(Array(Edge(Cap))) @pos : Array({Int32, Int32}) # $0$ 頂点 $0$ 辺のグラフを作ります。 # # ``` # graph = MaxFlowGraph(Int64).new # ``` def initialize @size = 0 @graph = [] of Array(Edge(Cap)) @pos = [] of {Int32, Int32} end # $n$ 頂点 $0$ 辺のグラフを作ります。 # # ``` # n = 10 # graph = MaxFlowGraph(Int64).new(n) # ``` def initialize(n : Int) @size = n.to_i32 @graph = Array.new(n) { Array(Edge(Cap)).new } @pos = [] of {Int32, Int32} end # 頂点 `from` から頂点 `to` へ最大容量 `cap`、流量 $0$ の辺を追加します。 # # 何番目に追加された辺であるかを返します。 # # ``` # n = 10 # graph = MaxFlowGraph(Int64).new(n) # graph.add_edge(0, 1, 1) # => 0 # graph.add_edge(1, 3, 2) # => 1 # graph.add_edge(5, 6, 8) # => 2 # ``` def add_edge(from : Int, to : Int, cap : Cap) : Int32 m = @pos.size @pos << {from.to_i32, @graph[from].size} from_id = @graph[from].size to_id = @graph[to].size to_id += 1 if from == to @graph[from] << Edge(Cap).new(to.to_i32, to_id, cap) @graph[to] << Edge(Cap).new(from.to_i32, from_id, Cap.zero) m end # 今の内部の辺の状態を返します。 # # 辺の順番は `add_edge` での追加順と同じです。 def get_edge(i : Int) e = @graph[@pos[i][0]][@pos[i][1]] re = @graph[e.to][e.rev] {from: @pos[i][0], to: e.to, cap: e.cap + re.cap, flow: re.cap} end # 今の内部の辺の状態を返します。 # # 辺の順番は `add_edge` での追加順と同じです。 def edges Array.new(@pos.size) { |i| get_edge(i) } end # $i$ 番目に変更された辺の容量、流量をそれぞれ `new_cap`, `new_flow` に変更します。 # # 他の辺の容量、流量は変更しません。 def change_edge(i : Int, new_cap : Cap, new_flow : Cap) @graph[@pos[i].first][@pos[i].second].cap = new_cap - new_flow @graph[_e.to][_e.rev].cap = new_flow end # 頂点 $s$ から頂点 $t$ へ流せるだけ流し、流せた量を返します。 # # 複数回呼ぶことも可能ですが、同じ結果を返すわけではありません。 # 挙動については以下を参考にしてください。 # - https://atcoder.github.io/ac-library/document_ja/appendix.html # # ``` # n = 4 # graph = MaxFlowGraph(Int64).new(n) # graph.add_edge(0, 1, 10) # => 0 # graph.add_edge(1, 2, 2) # => 1 # graph.add_edge(0, 2, 5) # => 2 # graph.add_edge(1, 3, 6) # => 3 # graph.add_edge(2, 3, 3) # => 4 # # graph.flow(0, 3) # => 9 # ``` def flow(s : Int, t : Int) flow(s, t, Cap::MAX) end # 頂点 $s$ から頂点 $t$ へ流せるだけ流し、流せた量を返します。 # # 複数回呼ぶことも可能ですが、同じ結果を返すわけではありません。 # 挙動については以下を参考にしてください。 # - https://atcoder.github.io/ac-library/document_ja/appendix.html # # ``` # n = 4 # graph = MaxFlowGraph(Int64).new(n) # graph.add_edge(0, 1, 10) # => 0 # graph.add_edge(1, 2, 2) # => 1 # graph.add_edge(0, 2, 5) # => 2 # graph.add_edge(1, 3, 6) # => 3 # graph.add_edge(2, 3, 3) # => 4 # # graph.flow(0, 3, 6) # => 6 # graph.flow(0, 3, 100) # => 9 (本来の挙動であれば 3 を返します。) # ``` # ameba:disable Metrics/CyclomaticComplexity def flow(s : Int, t : Int, flow_limit : Cap) level = [0] * @size iter = [0] * @size bfs = ->{ level = [-1] * @size level[s] = 0 que = Deque(Int32).new([s.to_i32]) until que.empty? v = que.shift @graph[v].each do |e| next if e.cap == 0 || level[e.to] >= 0 level[e.to] = level[v] + 1 next if e.to == t que << e.to end end } dfs = uninitialized Int32, Cap -> Cap dfs = ->(v : Int32, up : Cap) { return up if v == s res = Cap.zero level_v = level[v] (iter[v]...@graph[v].size).each do |i| e = @graph[v][i] next if level_v <= level[e.to] || @graph[e.to][e.rev].cap == 0 d = dfs.call(e.to, Math.min(up - res, @graph[e.to][e.rev].cap)) next if d <= 0 @graph[v][i].cap += d @graph[e.to][e.rev].cap -= d res += d return res if res == up end level[v] = @size res } res = Cap.zero while res < flow_limit bfs.call break if level[t] == -1 iter = [0] * @size f = dfs.call(t.to_i32, flow_limit - res) break if f == 0 res += f end res end # 長さ $n$ の配列を返します。 # $i$ 番目の要素には、頂点 $s$ から $i$ へ残余グラフで到達可能なとき、またその時のみ `true` を返します。 # # `flow(s, t)` を `flow_limit` なしでちょうど一回呼んだ後に呼ぶと、 # 返り値は $s, t$ 間の `mincut` に対応します。 def min_cut(s : Int) closed = [false] * @size que = Deque(Int32).new([s.to_i32]) unless que.empty? now = que.shift closed[now] = true @graph[now].each do |e| if e.cap != 0 && !closed[e.to] closed[e.to] = true que << e.to end end end closed end end end n, m = read_line.split.map &.to_i graph = NgLib::MaxFlowGraph(Int32).new(n) m.times do u, v, c = read_line.split.map &.to_i graph.add_edge(u, v, c) end ans = graph.flow(0, n - 1) puts ans