ZOJ2314:Reactor Cooling——題解
阿新 • • 發佈:2018-01-05
輸出 網絡流 mes const stream else node mda tdi
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314
題目大意:無源匯上下界網絡流,問每個管子走多少流量才能滿足所有管子的下界,如果沒有方案輸出“NO”。
————————————————————————
上下界網絡流無源匯板子題。
顯然參考了:https://www.cnblogs.com/kane0526/archive/2013/04/05/3001108.html
我們很直觀的想到:我們把上界-下界,下界=0,那麽不就可以跑正常流了?
顯然不對,這不滿足流量守恒定理。
於是我們考慮在它不平衡的時候人為的補充/流走流量。
當流入>流出,我們從st到該點建容量為流入-流出的邊。
當流入<流出,我們從該點到ed建容量為流出-流入的邊。
統計我們流入>流出時所有加的邊的容量和,如果容量和不等於最大流,顯然它不能保證所有邊的下邊界,就是no。
否則輸出所有原邊的反向邊此時的容量即可。
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=210; const int M=40010; const int INF=2147483640; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch==‘-‘;ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int nxt; int to; int w; }edge[M]; int head[2*N],low[M],out[N],in[N],cnt=-1; inline void add(int u,int v,int w){ cnt++; edge[cnt].to=v; edge[cnt].w=w; edge[cnt].nxt=head[u]; head[u]=cnt; return; } int lev[N],cur[N]; bool bfs(int m){//強制1為源點,m為匯點 int dui[m],r=0; for(int i=1;i<=m;i++){ lev[i]=-1; cur[i]=head[i]; } dui[0]=1,lev[1]=0; int u,v; for(int l=0;l<=r;l++){ u=dui[l]; for(int e=head[u];e!=-1;e=edge[e].nxt){ v=edge[e].to; if(edge[e].w>0&&lev[v]==-1){ lev[v]=lev[u]+1; r++; dui[r]=v; if(v==m)return 1; } } } return 0; } int dinic(int u,int flow,int m){ if(u==m)return flow; int res=0,delta; for(int &e=cur[u];e!=-1;e=edge[e].nxt){ int v=edge[e].to; if(edge[e].w>0&&lev[u]<lev[v]){ delta=dinic(v,min(edge[e].w,flow-res),m); if(delta>0){ edge[e].w-=delta; edge[e^1].w+=delta; res+=delta; if(res==flow)break; } } } if(res!=flow)lev[u]=-1; return res; } inline void init(){ memset(head,-1,sizeof(head)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); cnt=-1; return; } int main(){ int t=read(),num=0; while(t--){ init();num++; if(num>1)puts(""); int n=read(),m=read(); for(int i=1;i<=m;i++){ int u=read()+1,v=read()+1; low[i]=read(); int up=read(); add(u,v,up-low[i]); add(v,u,0); out[u]+=low[i]; in[v]+=low[i]; } int st=1,ed=n+2,ans=0,full=0; for(int i=2;i<=n+1;i++){ if(out[i]<in[i]){ add(st,i,in[i]-out[i]); add(i,st,0); full+=in[i]-out[i]; }else{ add(i,ed,out[i]-in[i]); add(ed,i,0); } } while(bfs(ed)==1)ans+=dinic(st,INF,ed); if(ans!=full)puts("NO"); else{ puts("YES"); for(int i=0;i<m;i++){ printf("%d\n",edge[i*2+1].w+low[i+1]); } } } return 0; }
ZOJ2314:Reactor Cooling——題解