Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
max_flow.hpp
[詳解]
1#pragma once
2#include "../../../kyopro_library/template.hpp"
3
4/// @brief 最大流
5struct MaxFlow {
6 /// @brief 辺構造体
7 struct Edge {
8 int from; ///< 始点
9 int to; ///< 終点
10 int rev; ///< 逆辺のインデックス
11 ll cap; ///< 容量
12 ll flow; ///< 流量
13 bool isrev;
14 Edge(int from, int to, ll cap, int rev, bool isrev): from(from), to(to), rev(rev), cap(cap), flow(0), isrev(isrev) {}
15 };
16
17 MaxFlow(int n): graph(n), level(n), iter(n) {}
18 MaxFlow()=default;
19
20 /// @brief 容量 cap の辺を追加する
21 void add_edge(int from, int to, ll cap) {
22 graph[from].push_back(Edge(from,to,cap,graph[to].size(),false));
23 graph[to].push_back(Edge(to,from,0,graph[from].size()-1,true));
24 }
25
26private:
27 vector<vector<Edge>> graph;
28 vector<int> level,iter;
29 void bfs(int s) {
30 fill(level.begin(),level.end(),-1); level[s]=0;
31 queue<int> que; que.push(s);
32 while(!que.empty()) {
33 int v=que.front(); que.pop();
34 for(auto &e: graph[v]) {
35 if(e.cap>0 && level[e.to]<0) {
36 level[e.to]=level[v]+1;
37 que.push(e.to);
38 }
39 }
40 }
41 }
42 ll dfs(int v, int t, ll f) {
43 if(v==t) return f;
44 for(int& i=iter[v]; i<(int)graph[v].size(); i++) {
45 auto& e=graph[v][i];
46 if(e.cap>0 && level[v]<level[e.to]) {
47 ll d=dfs(e.to,t,min(f,e.cap));
48 if(d>0) {
49 e.cap-=d,graph[e.to][e.rev].cap+=d;
50 e.flow+=d,graph[e.to][e.rev].flow-=d;
51 return d;
52 }
53 }
54 }
55 return 0;
56 }
57
58public:
59 /// @brief s から t への最大流を求める
60 /// @note O(V^2 E)
61 ll flow(int s, int t) {
62 ll ret=0;
63 while(true) {
64 bfs(s);
65 if(level[t]==-1) return ret;
66 fill(iter.begin(),iter.end(),0);
67 ll f;
68 while((f=dfs(s,t,INFL))>0) ret+=f;
69 }
70 }
71
72 /// @brief 直前に流したフローから最小カットを復元する
73 /// @brief 始点 v から到達可能か否か
74 vector<int> mincut(int v=0) {
75 vector<int> ret(graph.size()); ret[v]=true;
76 queue<int> que; que.push(v);
77 while(!que.empty()) {
78 int v=que.front(); que.pop();
79 for(auto& e:graph[v]) {
80 if(e.cap>0 && !ret[e.to] /*&& !e.isrev*/) {
81 ret[e.to]=true;
82 que.push(e.to);
83 }
84 }
85 }
86 return ret;
87 }
88
89 /// @brief 直前に流したフローの辺の情報を返す
91 vector<Edge> ret;
92 for(int i=0; i<graph.size(); i++) for(auto &e: graph[i]) if(!e.isrev) ret.push_back(e);
93 return ret;
94 }
95};
辺構造体
Definition max_flow.hpp:7
int to
終点
Definition max_flow.hpp:9
ll flow
流量
Definition max_flow.hpp:12
int from
始点
Definition max_flow.hpp:8
Edge(int from, int to, ll cap, int rev, bool isrev)
Definition max_flow.hpp:14
ll cap
容量
Definition max_flow.hpp:11
int rev
逆辺のインデックス
Definition max_flow.hpp:10
最大流
Definition max_flow.hpp:5
MaxFlow()=default
MaxFlow(int n)
Definition max_flow.hpp:17
vector< int > mincut(int v=0)
直前に流したフローから最小カットを復元する
Definition max_flow.hpp:74
ll flow(int s, int t)
s から t への最大流を求める
Definition max_flow.hpp:61
vector< Edge > get_edges()
直前に流したフローの辺の情報を返す
Definition max_flow.hpp:90
void add_edge(int from, int to, ll cap)
容量 cap の辺を追加する
Definition max_flow.hpp:21
const ll INFL
Definition template.hpp:9