网络流最大流——dinic

前段时间听了一位大佬的建议,学习了一下dinic算法。
下面直接就是dinic算法的思路(和ISAP很像):
1.从s开始bfs查深度,从u查到v的条件是u有一条到v的有向边及这条边的权值不为0。
2.dfs,一次查出多条增广路,从u查到v的条件是u有一条到v的权值不为0的有向边及u有剩余的流量。完成后重新执行1直到bfs中s无法到达t。
dinic中也同样可用当前弧优化。
下面是代码:

#include<iostream>
#define INF 0x3f3f3f
#define int long long
using namespace std;
int n,m,s,t;
struct node{
	int to;
	int nxt;
	int val;
}edge[10010];
int head[210],tot;
void addedge(int u,int v,int w){
	edge[++tot].to=v;
	edge[tot].val=w;
	edge[tot].nxt=head[u];
	head[u]=tot;
}
int q[210],he,ta;
int deep[210];
bool bfs(){
	for(int i=1;i<=n;i++){
		deep[i]=0;
	}
	q[1]=s;
	deep[s]=1;
	he=1;
	ta=1;
	while(he<=ta){
		int u=q[he];
		he++;
		for(int i=head[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			if(deep[v]==0&&edge[i].val!=0){
				deep[v]=deep[u]+1;
				q[++ta]=v;
			}
		}
	}
	return (deep[t]!=0);
}
int cur[210];
int dfs(int u,int flow){
	if(u==t){
		return flow;
	}
	int used=0;
	for(int i=cur[u];i;i=edge[i].nxt){
		cur[u]=i;
		int v=edge[i].to;
		if(deep[u]+1==deep[v]&&edge[i].val!=0){
			int use=dfs(v,min(flow,edge[i].val));
			if(use!=0){
				flow-=use;
				edge[i].val-=use;
				used+=use;
				if(i%2==1){
					edge[i+1].val+=use;
				}
				else{
					edge[i-1].val-=use;
				}
			}
			if(flow==0){
				break;
			}
		}
	}
	if(used==0){
		deep[u]=0;
	}
	return used;
}
int ans=0;
signed main(){
	cin>>n>>m>>s>>t;
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		addedge(u,v,w);
		addedge(v,u,0);
	}
	while(bfs()){
		for(int i=1;i<=n;i++){
			cur[i]=head[i];
		}
		ans+=dfs(s,INF);
	}
	cout<<ans;
	return 0;
}
posted @ 2022-04-11 19:34  zzzzzz2  阅读(54)  评论(0)    收藏  举报