LOJ#116. 有源匯有上下界最大流
阿新 • • 發佈:2020-12-11
在無源匯可行流的基礎上加一條源點到匯點流量inf的邊,然後(虛源點到虛匯點)跑最大流,匯點到源點流經的流量就是有源匯可行流x
然後刪除多加的源點到匯點的邊,再從源點到匯點跑最大流,得到最大流y,x+y就是有源匯有上下界最大流
#include<bits/stdc++.h> using namespace std; #define ll long long const ll maxn =505; const ll inf=1e18; ll head[maxn],cnt; struct E { ll to,next,flow; }e[maxn*maxn]; ll nex[maxn],dis[maxn]; void add(ll u,ll v,ll flow) { e[cnt].to=v; e[cnt].flow=flow; e[cnt].next=head[u]; head[u]=cnt++; e[cnt].to=u; e[cnt].flow=0; e[cnt].next=head[v]; head[v]=cnt++; } ll n,m,st,ed,d[maxn],num=0; void init() { cnt=0; memset(head,-1,sizeof(head)); } queue<ll>q; bool bfs() { while(!q.empty()) q.pop(); for(ll i=0;i<=ed+1;i++) nex[i]=head[i],dis[i]=inf; q.push(st);dis[st]=0; while(!q.empty()) { int u=q.front();q.pop(); //printf("u=%d\n",u); for(ll i=head[u];i!=-1;i=e[i].next) { ll v=e[i].to,flow=e[i].flow; //printf(" v=%d flow=%d\n",v,flow); if((flow>0)&&(dis[v]==inf)) { dis[v]=dis[u]+1; q.push(v); if(v==ed) return 1; } } } return 0; } ll dfs(ll u,ll w) { if(u==ed) return w; ll y=0; for(ll i=nex[u];(i!=-1)&&w;i=e[i].next) { nex[u]=i; ll v=e[i].to,flow=e[i].flow; if((flow>0)&&(dis[u]+1==dis[v])) { ll k=dfs(v,min(flow,w)); if(k==0) dis[v]=inf; y+=k; w-=k; e[i].flow-=k; e[i^1].flow+=k; } } return y; } ll slove() { ll ans=0; while(bfs()) { //for(int i=0;i<=ed;i++) printf("dis[%d]=%d\n",i,dis[i]); ans+=dfs(st,inf); //printf("-ans=%d\n",ans); } return ans; } int main() { ll s1,t1; scanf("%lld %lld %lld %lld",&n,&m,&s1,&t1); init();st=0,ed=n+1; for(ll i=1;i<=m;i++) { ll u,v,x,y; scanf("%lld %lld %lld %lld",&u,&v,&x,&y); add(u,v,y-x); d[u]-=x;d[v]+=x; } num=0; for(ll i=1;i<=n;i++) { if(d[i]>0) add(st,i,d[i]),num+=d[i]; if(d[i]<0) add(i,ed,-d[i]); }add(t1,s1,inf); ll ans=slove(); //printf("ans=%lld\n",ans); if(ans!=num) { printf("please go home to sleep\n"); return 0; } st=s1,ed=t1; ans=e[cnt].flow; e[cnt].flow=e[cnt^1].flow=0; ans+=slove(); printf("%lld\n",ans); return 0; }