P3376网络流dinic

//5e3+5不够,以后都+10 保险起见 
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=210,maxe=5e3+5;
typedef long long ll;
int n,m,s,t;
ll ans,tot,head[maxn<<1],d[maxn<<1];
struct edge{
	ll to,nex,w; 	
}e[maxe<<1];
void adde(int u,int v,int w){
	e[++tot]={v,head[u],w};
	head[u]=tot;
}
bool bfs(){//s到t 
	int u;
	queue<int>q;
	memset(d,0,sizeof(d));
	q.push(s),d[s]=1;
	while(!q.empty()){
		u=q.front(),q.pop();
		for(int i=head[u];i;i=e[i].nex){
			int v=e[i].to;
			if(e[i].w&&!d[v]){//d[v]没到达过 
				q.push(v);
				d[v]=d[u]+1;//按边数分层 
				if(v==t) return true;//找到 可到达终点的路 了 
			}
		}
	}
	return false;
}
ll dfs(int u,ll in){
	if(u==t) return in;
	ll out=0;
	for(int i=head[u];i&&in;i=e[i].nex){//in!=0说明还有余量 
		int v=e[i].to;
		if(e[i].w&&d[v]==d[u]+1){
		//==是为了:每次尝试给予时,只往下一层走,防止混乱 
			ll res=dfs(v,min(in,e[i].w));
			//in是该路径走到当前位置的最小流, 
			e[i].w-=res;
			e[i^1].w+=res;//^求反向边
			in-=res;
			out+=res; 
		}
	}
	if(out==0) d[u]=0;//与t不连通,下次可以不用考虑该路 
	return out;
}
ll dinic(int s,int t){
	ll flow,maxf=0;
	while(bfs())
		while(flow=dfs(s,inf))
			maxf+=flow;
	return maxf; 
}
int main(){
	int u,v,w;
	scanf("%d%d%d%d",&n,&m,&s,&t);
	tot=1;//tot为什么初始化不为0,方便异或找 奇偶 反向边? 
	memset(head,0,sizeof(head));
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&u,&v,&w);
		adde(u,v,w);
		adde(v,u,0);
	}
	printf("%lld\n",dinic(s,t));	 
}

猜你喜欢

转载自blog.csdn.net/weixin_50904510/article/details/120394083