zoukankan      html  css  js  c++  java
  • 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
    ",edge[i*2+1].w+low[i+1]);
            }
        }
        }
        return 0;
    }
  • 相关阅读:
    Azure 虚拟机安全加固整理
    AzureARM 使用 powershell 扩容系统磁盘大小
    Azure Linux 云主机使用Root超级用户登录
    Open edX 配置 O365 SMTP
    powershell 根据错误GUID查寻错误详情
    azure 创建redhat镜像帮助
    Azure Powershell blob中指定的vhd创建虚拟机
    Azure Powershell 获取可用镜像 PublisherName,Offer,Skus,Version
    Power BI 连接到 Azure 账单,自动生成报表,可刷新
    Azure powershell 获取 vmSize 可用列表的命令
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8206508.html
Copyright © 2011-2022 走看看