int d[maxn];
int now[maxn];
int st,ed;
void add_dinic(int u, int v)
{
e[++cnt].v = v;
e[cnt].w = 0;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int dfs_dinic(int x, int flow)
{
if (x == ed) return flow;
int res = 0;
for (int i = now[x]; i != -1; i = e[i].nxt)
{
int v = e[i].v;
now[x]=i;
if (d[v] + 1 == d[x] && e[i].w > 0)
{
int k = dfs_dinic(v, min(e[i].w, flow));
res += k;
flow -= k;
e[i].w -= k;
e[i ^ 1].w += k;
if (!flow) break;
}
}
return res;
}
bool bfs_dinic()
{
memset(d, 0, sizeof(d));
queue<int>q;
q.push(ed);
d[ed] = 1;
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; i != -1; i = e[i].nxt)
{
int v = e[i].v;
if (!d[v] && e[i ^ 1].w > 0)
{
q.push(v);
d[v] = d[u] + 1;
}
}
}
return d[st] > 0;
}
int dinic()
{
int flow = 0;
while (bfs_dinic())
{
for (int i = 0; i <= ed; i++) now[i] = head[i];
flow += dfs_dinic(st, INF);
}
return flow;
}