Loading

网络最大流复习笔记

因为这是复习笔记,所以不是给完全不知道网络流的人看的。

Dinic。多次增广。每次增广前使用 BFS 对图分层。不能到达汇点则退出。

每次使用 DFS 增广。找增广路时,只找比当前点层数多 \(1\) 的。

两个优化:

  1. 多路增广。如果有残余流量没有用完,则再找一条。
  2. 当前弧优化。不走已经增广过的边。

注意要加反向边。

下面是简化后的以前写的代码。

#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 的边界条件是到达 tdfs 下一个时流量为 min(arc[i].flow,flow-used)dfs 的返回值为用过的流量。如果流量用完说明这条路走不通,不改变。

posted @ 2022-11-11 21:30  hihihi198  阅读(26)  评论(0)    收藏  举报