在一般的网络流中,FF和EK可能会造成一定的不稳定性而导致时间复杂度激增,而我们可以结合两个的优点和分层图来进行优化
其实Dinic算法可以理解为在分层图上跑FF算法,可以利用一些性质来进行优化
Dinic算法不断重复以下步骤,直到参量网络中S不能到达T
1.在残量网络上BFS求出分层图
2.在分层图上DFS寻找增广路,回溯时更新剩余容量。
有一些常用的剪枝
-
当前弧优化,每次刷完一条边时把对应的\(lnk[x]\)对应到下一位,下一次开始刷的时候从新的\(lnk[x]\)就可以了,具体实现用\(now[x]\)
-
把增广完毕的点的\(d[x]\)设为\(0\)下次不需要再增广此节点了
一道模板题
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=205,maxe=10005;
const LL INF=(LL)1<<60;
int S,T,N,M;
int son[maxe],nxt[maxe],lnk[maxn],cnt;
LL w[maxe],Ans;
int Q[maxn],d[maxn],now[maxn];
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline void add_e(int x,int y,int z){
son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;w[cnt]=z;
}
bool bfs(){
memset(d,0,sizeof d);
int hed=0,til=1;Q[til]=S;now[S]=lnk[S];d[S]=1;
while(hed!=til){
hed++;
for(int j=lnk[Q[hed]];j;j=nxt[j]){
if(w[j]&&!d[son[j]]){
Q[++til]=son[j];
now[son[j]]=lnk[son[j]];
d[son[j]]=d[Q[hed]]+1;
if(son[j]==T)return 1;
}
}
}
return 0;
}
LL dinic(int x,LL flow){
if(x==T)return flow;
LL rest=flow,k=0,j;
for(j=now[x];j&&rest;j=nxt[j])
if(w[j]&&d[son[j]]==d[x]+1){
k=dinic(son[j],min(rest,w[j]));
if(!k)d[son[j]]=0;
w[j]-=k;w[j^1]+=k;
rest-=k;
}
now[x]=j;
return flow-rest;
}
int main(){
freopen("P3376.in","r",stdin);
freopen("P3376.out","w",stdout);
N=read();M=read();S=read();T=read();
cnt=1;
for(int i=1;i<=M;i++){
int x=read(),y=read(),z=read();
add_e(x,y,z);add_e(y,x,0);
}
LL flow=0;
while(bfs())
while(flow=dinic(S,INF))
Ans+=flow;
printf("%lld\n",Ans);
return 0;
}