ISAP优化DINIC,虽然并没有找到卡dinic不卡ISAP的题,但是还是有用。
DINIC每次全局分层,ISAP动态维护深度。
从终点开始赋值深度,这样起点的深度是最大的。
一旦有一条边使用过了,我们就讲v的深度加1,意义是它和u的深度现在是一样的,两点之间的边不能用了。
同理,走到下一个点的条件是dep[u]=dep[v]+1.
与此同时,加一个cnt记录每个深度的点数。
如果一个深度没有点了,那这个图就没有增广路了。
相当于是将全局逐渐缩点,最后没了就没了。
然后复杂度会好看一点。
#include<bits/stdc++.h>
using namespace std;
#define in read()
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
int first[100003],nxt[200003],to[200003],w[200003],tot=1;
void add(int a,int b,int c){
nxt[++tot]=first[a];first[a]=tot;to[tot]=b;w[tot]=c;
nxt[++tot]=first[b];first[b]=tot;to[tot]=a;w[tot]=0;
}
int n,m,s,t;
int maxflow;int cnt[100003];
int dep[100003];queue<int> q;
void bfs(int S,int T){
memset(dep,-1,sizeof(dep));
dep[T]=0;q.push(T);cnt[0]++;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=first[u];i;i=nxt[i]){
int v=to[i];if(dep[v]==-1){
dep[v]=dep[u]+1;cnt[dep[v]]++;q.push(v);
}
}
}
}
int dfs(int now,int T,int limit){
if(now==T||!limit){
maxflow+=limit;
return limit;
}
int flow=0,f=0;
for(int i=first[now];i;i=nxt[i]){
int v=to[i];if(dep[v]==dep[now]-1&&(f=dfs(v,T,min(limit,w[i])))){
flow+=f;w[i]-=f;w[i^1]+=f;limit-=f;if(!limit)return flow;
}
}
if(!--cnt[dep[now]]){
dep[s]=n+1;
}
++cnt[++dep[now]];
return flow;
}
void dinic(int S,int T){
bfs(S,T);
while(dep[S]<n){
// for(int i=1;i<=n;i++)cout<<dep[i]<<" ";cout<<endl;
dfs(S,T,0x3f3f3f3f);
}
}
signed main(){
n=in;m=in;s=in;t=in;
for(int i=1;i<=m;i++){
int x,y,z;x=in;y=in;z=in;add(x,y,z);
}
dinic(s,t);
cout<<maxflow;
return 0;
}