ZOJ2314:Reactor Cooling——题解

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;
}

 

posted @ 2018-01-05 19:39  luyouqi233  阅读(213)  评论(0编辑  收藏  举报