网络流-最大流EK算法

源点S,汇点T
通过bfs找到增广路,并逆序构建残留网
累加可行流即为答案
链式前向星存图
注意边的编号从2开始,这是为了让编号^1时,是我们构建的退流管道边(即2的退流管道为3,4的退流管道为5...)
时间复杂度O(n*m^2)

int S,T;
struct edge{
	int v,w,ne;
}e[maxn];
int idx=1;
int mf[maxn],pre[maxn];
//mf数组用来存节点v到源点S之间能通过的最大流量
int h[maxn];
void add(int a,int b,int c){
	e[++idx]={b,c,h[a]};h[a]=idx;
}
bool bfs(){
	memset(mf,0,sizeof mf);
	queue<int>q;
	q.push(S);mf[S]=1e9;
	while(q.size()){
		int u=q.front();q.pop();
		for(int i=h[u];i;i=e[i].ne){
			int v=e[i].v;
			if(mf[v]==0&&e[i].w){
				mf[v]=min(mf[u],e[i].w);
				pre[v]=i;//记录每一个节点的前驱边,以便接下来的逆序
				q.push(v);
				if(v==T)return true;	
			}
		}
	}
	return false;
}
int EK(){
	int flow=0;
	while(bfs()){
		int v=T;
		while(v!=S){
			int i=pre[v];
			e[i].w-=mf[T];
			e[i^1].w+=mf[T];//退流管道
			v=e[i^1].v;//(2->3)->4
		}
		flow+=mf[T];
	}
	return flow;
}
void solve(){
	int n,m;cin>>n>>m;
	cin>>S>>T;
	rep(i,1,m){
		int u,v,w;cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,0);//构建退流管道
	}
	cout<<EK()<<endl;
}
posted @ 2025-04-17 18:53  Marinaco  阅读(19)  评论(0)    收藏  举报
//雪花飘落效果