【ZOJ2314】Reactor Cooling(有上下界的網路流)
阿新 • • 發佈:2019-01-12
前言
話說有上下界的網路流好像全機房就我一個人會手動滑稽,當然這是不可能的
Solution
其實這道題目就是一道板子題,主要講解一下怎麼做無源無匯的上下界最大流:
演算法步驟
1.將每條邊轉換成0~up-down。
但是,我們發現轉換的時候不能保證一定是流量守恆。
2.可以把一條邊的起點都減去下界,終點加上上界。令這個陣列為\(d\)
3.對於\(d_i<0\),那麼向匯點連條邊;對於\(d_i>0\),從源點連邊。
4.最後從源點到匯點跑一邊Dinic就好了。
程式碼實現
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<set> #include<map> #include<iostream> using namespace std; #define ll long long #define re register #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) inline int gi(){ int f=1,sum=0;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return f*sum; } const int N=210,M=200010,Inf=1e9+10; int front[N],nxt[M<<1],to[M<<1],w[M<<1],cnt,id[M<<1],n,m,d[N],ans[M<<1]; void Add(int u,int v,int val,int Id){ to[cnt]=v;nxt[cnt]=front[u];front[u]=cnt;w[cnt]=val;id[cnt++]=Id; } int val[M],s,t,flow,dep[N]; void init(){ memset(front,-1,sizeof(front));cnt=0; memset(to,0,sizeof(to));memset(nxt,0,sizeof(nxt)); memset(w,0,sizeof(w)); } bool bfs(){ memset(dep,0,sizeof(dep)); queue<int >Q;while(!Q.empty())Q.pop(); Q.push(s);dep[s]=1; while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=front[u];i!=-1;i=nxt[i]){ int v=to[i]; if(!dep[v] && w[i]){ dep[v]=dep[u]+1; Q.push(v); } } } return dep[t]; } int dfs(int u,int Flow){ if(u==t || !Flow)return Flow; for(int i=front[u];i!=-1;i=nxt[i]){ int v=to[i]; if(dep[v]==dep[u]+1 && w[i]){ int di=dfs(v,min(Flow,w[i])); if(di){ w[i]-=di;w[i^1]+=di; return di; } } } return 0; } int Dinic(){ int Flow=0; while(bfs()) while(int d=dfs(s,Inf))Flow+=d; return Flow; } int main(){ int T=gi(); while(T--){ init(); n=gi();m=gi();s=0;t=n+1;memset(d,0,sizeof(d)); for(int i=1;i<=m;i++){ int u=gi(),v=gi(),l=gi(),c=gi(); d[u]-=l; d[v]+=l; Add(u,v,c-l,i);Add(v,u,0,0); val[i]=l; } for(int i=1;i<=n;i++){ if(d[i]>0){Add(s,i,d[i],0);Add(i,s,0,0);} if(d[i]<0){Add(i,t,-d[i],0);Add(t,i,0,0);} } flow=Dinic();bool flag=true; for(int i=front[s];i!=-1;i=nxt[i]) if(w[i]>0){flag=false;break;} if(!flag)puts("NO"); else{ puts("YES"); for(int i=0;i<cnt;i++)ans[id[i]]=w[i^1]; for(int i=1;i<=m;i++) printf("%d\n",ans[i]+val[i]); } puts(""); } return 0; }f