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
19 /// @brief 容量 cap の辺を追加する
20 void add_edge(int from, int to, ll cap) {
21 graph[from].push_back(Edge(from,to,cap,graph[to].size(),false));
22 graph[to].push_back(Edge(to,from,0,graph[from].size()-1,true));
23 }
24
25private:
26 vector<vector<Edge>> graph;
27 vector<int> level,iter;
28 void bfs(int s) {
29 fill(level.begin(),level.end(),-1);
30 queue<int> que;
31 level[s]=0;
32 que.push(s);
33 while(!que.empty()) {
34 int v=que.front();
35 que.pop();
36 for(auto &e:graph[v]) {
37 if(e.cap>0&&level[e.to]<0) {
38 level[e.to]=level[v]+1;
39 que.push(e.to);
40 }
41 }
42 }
43 }
44 ll dfs(int v, int t, ll f) {
45 if(v==t) return f;
46 for(int& i=iter[v]; i<(int)graph[v].size(); i++) {
47 auto& e=graph[v][i];
48 if(e.cap>0&&level[v]<level[e.to]) {
49 ll d=dfs(e.to,t,min(f,e.cap));
50 if(d>0) {
51 e.cap-=d,graph[e.to][e.rev].cap+=d;
52 e.flow+=d,graph[e.to][e.rev].flow-=d;
53 return d;
54 }
55 }
56 }
57 return 0;
58 }
59
60public:
61 /// @brief s から t への最大流を求める
62 /// @note O(V^2 E)
63 ll flow(int s, int t) {
64 ll ret=0;
65 while(true) {
66 bfs(s);
67 if(level[t]==-1) return ret;
68 fill(iter.begin(),iter.end(),0);
69 ll f;
70 while((f=dfs(s,t,INFL))>0) ret+=f;
71 }
72 }
73
74 /// @brief 直前に流したフローから最小カットを復元する
75 /// @brief 始点 v から到達可能か否か
76 vector<int> mincut(int v=0) {
77 vector<int> ret(graph.size());
78 queue<int> que;
79 que.push(v);
80 ret[v]=true;
81 while(!que.empty()) {
82 int v=que.front();
83 que.pop();
84 for(auto& e:graph[v]) {
85 if(e.cap>0&&!ret[e.to]) {
86 ret[e.to]=true;
87 que.push(e.to);
88 }
89 }
90 }
91 return ret;
92 }
93
94 /// @brief 直前に流したフローの辺の情報を返す
96 vector<Edge> ret;
97 for(int i=0; i<graph.size(); i++) for(auto &e:graph[i]) if(!e.isrev) ret.push_back(e);
98 return ret;
99 }
100};
辺構造体
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(int n)
Definition max_flow.hpp:17
vector< int > mincut(int v=0)
直前に流したフローから最小カットを復元する
Definition max_flow.hpp:76
ll flow(int s, int t)
s から t への最大流を求める
Definition max_flow.hpp:63
vector< Edge > get_edges()
直前に流したフローの辺の情報を返す
Definition max_flow.hpp:95
void add_edge(int from, int to, ll cap)
容量 cap の辺を追加する
Definition max_flow.hpp:20
const ll INFL
Definition template.hpp:13