from zzugzx
//dinic
int n,m,s,t,N;
struct edge{
int v,nx;
int f;
}e[maxn];
int head[maxn],cnt,cur[maxn],dep[maxn];
void init(){
cnt=0;
for(int i=0;i<=N;i++)
head[i]=-1;
}
void add(int u,int v,int w){
e[cnt]={v,head[u],w};
head[u]=cnt++;
e[cnt]={u,head[v],0};
head[v]=cnt++;
}
bool bfs(){
for(int i=0;i<=N;i++)cur[i]=head[i],dep[i]=0;
queue<int> q;
q.push(s);dep[s]=1;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=e[i].nx){
int v=e[i].v;
if(e[i].f&&!dep[v]){
dep[v]=dep[u]+1;
if(v==t)return 1;
q.push(v);
}
}
}
return 0;
}
int dfs(int u,int lim){
if(u==t)return lim;
int ans=0,v,tmp;
for(int i=cur[u];i!=-1;i=e[i].nx){
cur[u]=i;
v=e[i].v;
if(dep[v]==dep[u]+1&&e[i].f){
tmp=dfs(v,min(lim,e[i].f));
e[i].f-=tmp;
e[i^1].f+=tmp;
ans+=tmp;
lim-=tmp;
if(!lim)break;
}
}
if(!ans||lim)dep[u]=0;
return ans;
}
int dinic(){
int ans=0;
while(bfs())ans+=dfs(s,inf);
return ans;
}
int n,m,s,t, N;
struct Edge {
int v,w,next;
}e[300005 * 10];
int head[300005],cnt;
void add(int u,int v,int w)
{
cnt++;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
cnt++;
e[cnt].v=u;
e[cnt].w=0;
e[cnt].next=head[v];
head[v]=cnt;
}
int gap[300005],d[300005],cur[300005];
queue <int> que;
void init(int s,int t)
{
for (int i = 0; i <= 2 * n + 1; i ++)
d[i] = 0, gap[i] = 0, cur[i] = head[i];
d[t]=1,gap[1]++;
que.push(t);
while (!que.empty()) {
int x=que.front();
que.pop();
for (int i=head[x];i;i=e[i].next) {
if (!d[e[i].v]) {
d[e[i].v]=d[x]+1;
gap[d[x]+1]++;
que.push(e[i].v);
}
}
}
}
int dfs(int x,int s,int t,int flow)
{
if (x==t) return flow;
int flowed=0;
for (int &i=cur[x];i;i=e[i].next)
{//当前弧优化
if (d[x]==d[e[i].v]+1)
{//最短流
int tmp=dfs(e[i].v,s,t,min(flow,e[i].w));
flowed+=tmp,flow-=tmp,e[i].w-=tmp,e[i^1].w+=tmp;
if (!flow) return flowed;
}
}
gap[d[x]]--;
if (!gap[d[x]]) d[s]= 2 * n + 3;//gap优化
d[x]++;
gap[d[x]]++;
cur[x]=head[x];
return flowed;
}
int ISAP(int s,int t)
{
init(s,t);
int ret=0;
while(d[s]<=2 * n + 2)
ret+=dfs(s,s,t,inf);
return ret;
}