struct Edge {
int lst;
int v;
int w;
};
const int maxn = 1e5+500;
const int maxe = (1e5+500) * 2;
const int inf = 0x3f3f3f3f;
class ISAP {
public :
Edge edge[maxe];
int head[maxn], qsz;
int d[maxn], cur[maxn], num[maxn];
int st, ed, n;
void add(int u, int v, int w) {
edge[qsz] = (Edge){head[u], v, w};
head[u] = qsz++;
edge[qsz] = (Edge){head[v], u, w};
head[v] = qsz++;
}
void bfs(int t) {
queue<int> q;
memset(num, 0, sizeof(num));
memset(d, 0, sizeof(d));
for (int i=1; i<=n; ++i) cur[i] = head[i];
d[t] = 1;
num[d[t]]++;
q.push(t);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i=head[u]; ~i; i=edge[i].lst) {
int v = edge[i].v;
if (!d[v]) {
d[v] = d[u] + 1;
num[d[v]]++;
q.push(v);
}
}
}
}
int dfs(int u, int limit) {
if (u==ed) return limit;
int flow = 0, v;
for (int i=cur[u]; ~i; i=cur[u]=edge[i].lst) {
v = edge[i].v;
if (d[u] == d[v] + 1) {
int f = dfs(v, min(limit, edge[i].w));
flow += f;
limit -= f;
edge[i].w -= f;
edge[i^1].w += f;
if (!limit) return flow;
}
}
if (!(--num[d[u]])) d[st] = n + 1;
d[u] += 1;
++num[d[u]];
cur[u] = head[u];
return flow;
}
void init(int n) {
this->n = n;
qsz = 0;
memset(head, -1, sizeof head);
}
int maxflow(int st, int ed) {
bfs(ed);
this->st = st; this->ed = ed;
int res = 0;
do {
res += dfs(st, inf);
} while (d[st] <= n);
return res;
}
}isap;