有源汇有上下界最小流

Loj117模板

  • 和最大流类似,最大流找到可行流后增流,最小流找到可行流后退流

Code


#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define ll long long
using namespace std;
const int inf=1e10;
const int N=5e4+10;
const int M=1e6;
struct node{int n,y;ll v;}e[M];
int lin[N],cur[N],D[N],d[N],maxflow1=0,maxflow2=0,len=1,n,m,s,t,S,T,x,y,l,r;
void read(int x,int y,int v){e[++len].y=y,e[len].v=v,e[len].n=lin[x],lin[x]=len;}
void add(int x,int y,int v){read(x,y,v),read(y,x,0);}
int hazard(){
	int num=0,f=1;char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)){num=(num<<1)+(num<<3)+ch-'0';ch=getchar();}
	return num*f;
}
bool bfs(int s,int t){
	memset(d,0,sizeof(d));queue<int> q;
	d[s]=1,q.push(s);
	while(q.size()){
		int x=q.front();q.pop();
		for(int i=lin[x];i;i=e[i].n){
			int y=e[i].y;
			if(!e[i].v||d[y])continue;
			d[y]=d[x]+1;
			q.push(y);
		}
	}
	return d[t]>0;
}
ll dfs(int x,int t,ll minf){
	if(x==t)return minf;
	ll flow=0,sum=0;
	for(int i=lin[x];i;i=e[i].n){
		int y=e[i].y;
		if(e[i].v&&d[y]==d[x]+1){
			flow=dfs(y,t,min(minf,e[i].v));
			if(!flow)d[y]=0;
			sum+=flow,minf-=flow,e[i].v-=flow,e[i^1].v+=flow;
			minf-=flow;if(!minf)return sum;
		}
	}return sum;
}
ll dinic(int s,int t){ll maxflow=0;while(bfs(s,t))maxflow+=dfs(s,t,inf);return maxflow;}
int main()
{
	n=hazard(),m=hazard(),s=hazard(),t=hazard();S=n+1,T=S+1;
	rep(i,1,m){x=hazard(),y=hazard(),l=hazard(),r=hazard();add(x,y,r-l);D[y]+=l,D[x]-=l;}
	rep(i,1,n)if(D[i]>0)add(S,i,D[i]);else add(i,T,-D[i]);
	add(t,s,inf);
	dinic(S,T);
	maxflow1=e[len].v;
	e[len].v=e[len-1].v=0;
	maxflow2=dinic(t,s);
	for(int i=lin[S];i;i=e[i].n)if(e[i].v){puts("please go home to sleep");return 0;}
	printf("%d\n",maxflow1-maxflow2);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值