zoukankan      html  css  js  c++  java
  • zoj 2314 Reactor Cooling 夜

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314

    大牛就是大牛  人家能想到咱就是想不到呀

    根据所给流量下限(下限必流)

    记录每个点的入度(in) 和出度(out)  然后用(上限-下限)进行建图 (这是还可以增加的流)

    然后虚拟起点和汇点  根据每个点的 in 和 out 

    如果 in > out 说明此点需要流出(in - out ) 然后从起点连一条边 流为( in - out ) 等于给此点一个流出的机会

    如果 in < out 说明此点需要流入 (out - in ) 然后向终点连一条边 流为 ( out - in ) 等于给此点一个流入的机会

    然后求最大流  看是否最大流为满流(既等于初始化时从起点需要流出的量 且等于初始化时需要向汇点流入的量)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<set>
    #include<vector>
    #include<stack>
    #include<queue>
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #define ll long long
    
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int MOD=100000007;
    const int N=205;
    const int M=100005;
    int head[N],I;
    struct node
    {
        int j,next;
        int k;
        int flow;
    }edge[M];
    struct node1
    {
        int l,r,low,high;
    }p[M];
    int in[N],out[N];
    int L[N];
    int st,nd;
    void add(int i,int j,int flow,int k)
    {
        edge[I].j=j;
        edge[I].k=k;
        edge[I].flow=flow;
        edge[I].next=head[i];
        head[i]=I++;
    }
    bool bfs(int x1,int x2)
    {
        memset(L,-1,sizeof(L));
        queue<int>qt;
        qt.push(x1);
        L[x1]=0;
        while(!qt.empty())
        {
            int x=qt.front();
            qt.pop();
            for(int t=head[x];t!=-1;t=edge[t].next)
            {
                int j=edge[t].j;
                if(edge[t^1].flow>0&&L[j]==-1)
                {
                    L[j]=L[x]+1;
                    qt.push(j);
                }
            }
        }
        if(L[x2]==-1)
        return false;
        return true;
    }
    int dfs(int x,int sum)
    {
        if(x==nd)
        return sum;
        int tmp=sum;
        for(int t=head[x];t!=-1;t=edge[t].next)
        {
            int j=edge[t].j;
            if(edge[t].flow>0&&L[x]==L[j]+1)
            {
                int w=dfs(j,min(tmp,edge[t].flow));
                edge[t].flow-=w;int k=edge[t].k;if(k!=-1)p[k].low+=w;
                edge[t^1].flow+=w;k=edge[t^1].k;if(k!=-1)p[k].low-=w;
                tmp-=w;
                if(tmp==0)
                break;
            }
        }
        return (sum-tmp);
    }
    void init(int n,int m,int st,int nd,int &S,int &E)
    {
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        for(int i=0;i<m;++i)
        {
            cin>>p[i].l>>p[i].r>>p[i].low>>p[i].high;
            out[p[i].l]+=p[i].low;
            in[p[i].r]+=p[i].low;
            add(p[i].l,p[i].r,p[i].high-p[i].low,i);
            add(p[i].r,p[i].l,0,-1);
        }
        for(int i=1;i<=n;++i)
        {
            if(in[i]>out[i])
            {
                add(st,i,in[i]-out[i],-1);
                add(i,st,0,-1);
                S+=(in[i]-out[i]);
            }
            if(in[i]<out[i])
            {
                add(i,nd,out[i]-in[i],-1);
                add(nd,i,0,-1);
                E+=(out[i]-in[i]);
            }
        }
    }
    int main()
    {
        //freopen("data.in","r",stdin);
        int T;
        cin>>T;
        while(T--)
        {
            int n,m;
            while(cin>>n>>m)//cout<<n<<m<<endl;
            {
                memset(head,-1,sizeof(head));
                I=0;
                st=0;
                nd=n+1;
                int S=0,E=0;
                init(n,m,st,nd,S,E);//cout<<S<<" "<<E<<endl;
                int ans=0;
                while(bfs(nd,st))
                {
                    int k;
                    while((k=dfs(st,INF)))
                    ans+=k;
                }
                //cout<<ans<<" "<<S<<" "<<E<<endl;
                if(S==ans&&E==ans)
                {
                    cout<<"YES"<<endl;
                    for(int i=0;i<m;++i)
                    cout<<p[i].low<<endl;
                }
                else
                {
                    cout<<"NO"<<endl;
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    Linux进程和线程
    Vim编辑器
    Java多线程编程(七)线程状态、线程组与异常处理
    Java多线程编程(六)单例模式与多线程
    Integer to Roman
    Container With Most Water
    Regular Expression Matching
    Palindrome Number
    c/c++获取硬盘序列号
    String to Integer (atoi)
  • 原文地址:https://www.cnblogs.com/liulangye/p/3038588.html
Copyright © 2011-2022 走看看