namespace NetWorkFlow{
using namespace std;
#define int long long
#define fi first
#define se second
#define pb emplace_back
//最大流
template<class T>
struct MaxFlow{
struct edge{
int v;
T w;
edge(int v, T w) : v(v), w(w) {}
};
int n;
T MX = numeric_limits<T>::max();
vector<edge> G;
vector<vector<int> > g;
vector<int> dep, cur;
MaxFlow(){}
MaxFlow(int n){init(n);}
void init(int N){
n = N;
G.clear(), g.assign(n, {});
cur.resize(n), dep.resize(n);
}
bool bfs(int s, int t){
dep.assign(n, -1);
queue<int> q;
dep[s] = 0;
q.push(s);
while(!q.empty()){
int u = q.front();
q.pop();
for(int i : g[u]){
//auto [v, w] = G[i];
int v = G[i].v, w = G[i].w;
if(w > 0 && dep[v] == -1){
dep[v] = dep[u] + 1;
if(v == t) return 1;
q.push(v);
}
}
}
return 0;
}
T dfs(int u, int t, T f){
if(u == t) return f;
auto r = f;
for(int &i = cur[u]; i < g[u].size(); i++){
int j = g[u][i];
//auto [v, w] = G[j];
int v = G[j].v, w = G[j].w;
if(w > 0 && dep[v] == dep[u] + 1){
auto a = dfs(v, t, min(r, w));
G[j].w -= a;
G[j ^ 1].w += a;
r -= a;
if(r == 0) return f;
}
}
return f - r;
}
//加边
void add(int u, int v, T w){
g[u].pb(G.size()), G.pb(v, w);
g[v].pb(G.size()), G.pb(u, 0);
}
//最大流
T flow(int s, int t){
T ans = 0;
while(bfs(s, t)){
cur.assign(n, 0);
ans += dfs(s, t, MX);
}
return ans;
}
//最小割
vector<bool> minCut(){
vector<bool> w(n);
for(int i = 0; i < n; i++) w[i] = (dep[i] != -1);
return w;
}
//导出图
struct Edge{
int from, to;
T w, flow;
};
vector<Edge> edges(){
vector<Edge> a;
for(int i = 0; i < G.size(); i += 2){
Edge x;
x.from = G[i + 1].v;
x.to = G[i].v;
x.w = G[i].w + G[i + 1].w;
x.flow = G[i + 1].w;
a.push_back(x);
}
return a;
}
//上下界用
T get_flow(int x){return G[x ^ 1].w;}
void remove(int x){G[x].w = G[x ^ 1].w = 0;}
};
//Min Cost Max Flow
//最小费用最大流
template<class T>
struct MCMF{
struct edge{
int to;
T w, c;
edge(int to, T w, T c) : to(to), w(w), c(c) {}
};
int n;
T MX = numeric_limits<T>::max();
vector<edge> G;
vector<vector<int> > g;
vector<T> h, dis;
vector<int> pre;
MCMF(){}
MCMF(int N){init(N);}
void init(int N){
n = N;
G.clear(), g.assign(n, {});
}
//加边
void add(int u, int v, T w, T c){
g[u].pb(G.size()), G.pb(v, w, c);
g[v].pb(G.size()), G.pb(u, 0, -c);
}
bool dijkstra(int s, int t){
dis.assign(n, MX);
pre.assign(n, -1);
priority_queue<pair<T, int>, vector<pair<T, int> >, greater<pair<T, int> > > q;
dis[s] = 0;
q.emplace(0, s);
while(!q.empty()){
T d = q.top().fi;
int u = q.top().se;
q.pop();
if(dis[u] != d) continue;
for(int i : g[u]){
int v = G[i].to;
T w = G[i].w, c = G[i].c;
if(w > 0 && dis[v] > d + h[u] - h[v] + c){
dis[v] = d + h[u] - h[v] + c;
pre[v] = i;
q.emplace(dis[v], v);
}
}
}
return dis[t] != MX;
}
//最大流 and 最小费用
pair<T, T> flow(int s, int t){
T flow = 0;
T c = 0;
h.assign(n, 0);
while(dijkstra(s, t)){
for(int i = 0; i < n; i++) h[i] += dis[i];
T res = MX;
for(int i = t; i != s; i = G[pre[i] ^ 1].to){
res = min(res, G[pre[i]].w);
}
for(int i = t; i != s; i = G[pre[i] ^ 1].to){
G[pre[i]].w -= res;
G[pre[i] ^ 1].w += res;
}
flow += res;
c += res * h[t];
}
return {flow, c};
}
//导出图
struct Edge{
int from, to;
T w, c, flow;
};
vector<Edge> edges(){
vector<Edge> a;
for(int i = 0; i < G.size(); i += 2){
Edge x;
x.from = G[i + 1].v;
x.to = G[i].v;
x.w = G[i].w + G[i + 1].w;
x.c = G[i].c;
x.flow = G[i + 1].w;
a.push_back(x);
}
return a;
}
};
}