LOJ #117. 有源汇有上下界最小流
题面传送门
类似最大流,我们肯定要考虑在残量网络上搞事情。
对于最大流,我们是原流+残量网络上源到汇的最大流。
那么感性理解一下,最小流就是原流-残量网络上汇到源的最大流。
code:
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define l(x) x<<1
#define r(x) x<<1|1
#define re register
#define ll long long
#define db long double
#define N 100000
#define eps (1e-14)
#define mod 1000000007
#define Mod (mod-1)
using namespace std;
int n,m,st,t,S,T,d[N+5],nows[N+5],now,in[N+5],x,y,l,r,tot,ans;
struct yyy{int to,w,z;}tmp;
struct ljb{
int head,h[N+5];yyy f[N+5<<3];
I void add(int x,int y,int z){f[head]=(yyy){y,z,h[x]};h[x]=head++;}
}s;queue<int> q;
I void get(int x,int y,int z){s.add(x,y,z);s.add(y,x,0);}
I int bfs(){
memset(d,0x3f,sizeof(d));memset(nows,-1,sizeof(nows));while(!q.empty())q.pop();d[S]=0;q.push(S);nows[S]=s.h[S];
while(!q.empty()){
now=q.front();q.pop();for(int i=s.h[now];~i;i=tmp.z){
tmp=s.f[i];if(d[tmp.to]<1e9||!tmp.w) continue;d[tmp.to]=d[now]+1;
nows[tmp.to]=s.h[tmp.to];q.push(tmp.to);if(tmp.to==T) return 1;
}
}
return 0;
}
I int dfs(int x,int sum){
if(x==T) return sum;int k,pus=0,i;yyy tmp;for(int i=nows[x];~i;i=tmp.z){
tmp=s.f[i];nows[x]=i;if(d[tmp.to]!=d[x]+1||!tmp.w) continue;k=dfs(tmp.to,min(tmp.w,sum));
if(!k) d[tmp.to]=1e9;sum-=k;pus+=k;s.f[i].w-=k,s.f[i^1].w+=k;if(!sum) break;
}
return pus;
}
I void del(int x){s.h[x]=s.f[s.h[x]].z;}
int main(){
freopen("1.in","r",stdin);freopen("1.out","w",stdout);
re int i;scanf("%d%d%d%d",&n,&m,&st,&t);memset(s.h,-1,sizeof(s.h));T=n+1;for(i=1;i<=m;i++) scanf("%d%d%d%d",&x,&y,&l,&r),get(x,y,r-l),in[x]-=l,in[y]+=l;
for(i=1;i<=n;i++) in[i]>0?(tot+=in[i],get(S,i,in[i])):get(i,T,-in[i]);get(t,st,1e9);while(bfs()) tot-=dfs(S,1e9);if(tot){printf("please go home to sleep\n");return 0;}
ans=s.f[s.h[t]^1].w;del(t);del(st);S=t;T=st;while(bfs()) ans-=dfs(S,1e9);printf("%d\n",ans);
}