const int Maxn = 1e5;
const int Maxm = 1e5;
const LL Inf = 0x3f3f3f3f;
struct edge {
int to[Maxm * 2 + 5], Next[Maxm * 2 + 5]; LL val[Maxm * 2 + 5];
int len, Head[Maxn + 5];
edge () { len = 1; memset (Head, 0, sizeof Head); }
void Init () {
len = 1;
memset (Head, 0, sizeof Head);
}
void plus (int x, int y, LL w) {
to[++len] = y;
Next[len] = Head[x];
val[len] = w;
Head[x] = len;
}
void add (int x, int y, LL w) {
plus (x, y, w); plus (y, x, 0);
}
void rev_add (int x, int y, LL w) {
plus (y, x, w); plus (x, y, 0);
}
};
struct Max_Flow {
int s, t;
edge mp;
int hh, tt, q[Maxn + 5];
int depth[Maxn + 5], cur[Maxn + 5];
bool BFS () {
rep (i, 1, tt) depth[q[i]] = 0;
hh = 1; tt = 0; q[++tt] = s;
depth[s] = 1; cur[s] = mp.Head[s];
while (hh <= tt) {
int u = q[hh++];
for (int i = mp.Head[u]; i; i = mp.Next[i]) {
int v = mp.to[i]; LL w = mp.val[i];
if (w == 0) continue;
if (depth[v]) continue;
depth[v] = depth[u] + 1;
cur[v] = mp.Head[v];
q[++tt] = v;
if (v == t) return 1;
}
}
return 0;
}
LL DFS (int u, LL Up) {
if (u == t) return Up;
if (Up == 0) return 0;
LL flow = 0;
while (cur[u] && flow < Up) {
int i = cur[u]; cur[u] = mp.Next[cur[u]];
int v = mp.to[i]; LL w = mp.val[i];
if (w == 0) continue;
if (depth[v] != depth[u] + 1) continue;
LL tmp = DFS (v, Min (Up - flow, w));
if (tmp == 0) depth[v] = -1;
flow += tmp; mp.val[i] -= tmp; mp.val[i ^ 1] += tmp;
if (mp.val[i] && flow >= Up) cur[u] = i;
}
return flow;
}
LL Dinic () {
LL flow = 0;
while (BFS ()) {
flow += DFS (s, Inf);
}
return flow;
}
};