网络最大流复习笔记
因为这是复习笔记,所以不是给完全不知道网络流的人看的。
Dinic。多次增广。每次增广前使用 BFS 对图分层。不能到达汇点则退出。
每次使用 DFS 增广。找增广路时,只找比当前点层数多 \(1\) 的。
两个优化:
- 多路增广。如果有残余流量没有用完,则再找一条。
- 当前弧优化。不走已经增广过的边。
注意要加反向边。
下面是简化后的以前写的代码。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=250,M=5050,INF=0x3f3f3f3f;
int n,m,s,t,tot=1,head[N],q[N],hd,tl,cur[N],dep[N];
ll ans;
struct Arc{
int nxt,to,flow;
}arc[M<<1];
inline void addArc(int u,int v,int w){
arc[++tot].nxt=head[u];
arc[tot].to=v;
arc[tot].flow=w;
head[u]=tot;
}
bool bfs(){
for(int i=1;i<=n;i++)cur[i]=head[i];
memset(dep,0,sizeof(dep));
hd=tl=1;q[1]=s;dep[s]=1;
while(hd<=tl){
for(int u=q[hd++],i=head[u],v;~i;i=arc[i].nxt){
v=arc[i].to;
if(!dep[v]&&arc[i].flow>0){
dep[v]=dep[u]+1;
q[++tl]=v;
if(v==t)return 1;
}
}
}
return 0;
}
int dfs(int u,int flow){
if(u==t||flow<=0)return flow;
int used=0;
for(int i=cur[u],v,f;~i;i=arc[i].nxt){
v=arc[i].to;
cur[u]=i;
if(dep[v]==dep[u]+1&&(f=dfs(v,min(arc[i].flow,flow-used)))>0){
arc[i].flow-=f;
arc[i^1].flow+=f;
used+=f;
if(flow-used<=0)break;
}
}
return used;
}
int main(){
cin>>n>>m>>s>>t;
memset(head,-1,sizeof(head));
for(int i=1,u,v,w;i<=m;i++){
cin>>u>>v>>w;
addArc(u,v,w);
addArc(v,u,0);
}
while(bfs())ans+=dfs(s,INF);
printf("%lld",ans);
return 0;
}
可以发现理解以后还是非常好写的。
容易忘记的地方:dfs 的边界条件是到达 t。dfs 下一个时流量为 min(arc[i].flow,flow-used)。dfs 的返回值为用过的流量。如果流量用完说明这条路走不通,不改变。

浙公网安备 33010602011771号