首页 > 代码库 > ZOJ 2314/SGU194 Reactor Cooling

ZOJ 2314/SGU194 Reactor Cooling


无源汇点上下界可行流问题.....


建图:

对于一条边 u--->v  low(u,v) high(u,v) 连边 u--->v high(u,v) - low(u,v)  就变成了无上下界的网络流问题了

但这样不一定满足low的关系 ,所以我每要再每个点流量后面加上low.....

设自由流g(u,v)=high(u,v) - low(u,v)

每一个点的流量由自由流g和下界流low组成....




变一下型:




可以看到每个点流入流出的流量不一定平衡...


我们用一个数组low记录每个点的下界流量 , 当low[i]<0时流入的下界流小于流出的下界流,也就是

既流出少了 . 我们建一个超级汇点 连一条 i--->T 容量为 -Low[i] 的边.


当Low[i]>0 同理 流入的少了. 建一个超级源点 连一条 S--->i   容量为 Low[i]的边 ... 图就建好了


一个可行流,一定是一个从附加源到附加汇的最大流。而且源点所连的边一定是满流的。


所以跑一遍最大流最后判断一下源点说连的边是否满流,如果满流 说明 存在可行流。没满流,则不存在可行流。


Reactor Cooling

Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge

The terrorist group leaded by a well known international terrorist Ben Bladen is buliding a nuclear reactor to produce plutonium for the nuclear bomb they are planning to create. Being the wicked computer genius of this group, you are responsible for developing the cooling system for the reactor.

The cooling system of the reactor consists of the number of pipes that special cooling liquid flows by. Pipes are connected at special points, called nodes, each pipe has the starting node and the end point. The liquid must flow by the pipe from its start point to its end point and not in the opposite direction.

Let the nodes be numbered from 1 to N. The cooling system must be designed so that the liquid is circulating by the pipes and the amount of the liquid coming to each node (in the unit of time) is equal to the amount of liquid leaving the node. That is, if we designate the amount of liquid going by the pipe from i-th node to j-th as fij, (put fij = 0 if there is no pipe from node i to node j), for each i the following condition must hold:

fi,1+fi,2+...+fi,N = f1,i+f2,i+...+fN,i

Each pipe has some finite capacity, therefore for each i and j connected by the pipe must be fij <= cij where cij is the capacity of the pipe. To provide sufficient cooling, the amount of the liquid flowing by the pipe going from i-th to j-th nodes must be at least lij, thus it must be fij >= lij.

Given cij and lij for all pipes, find the amount fij, satisfying the conditions specified above.


This problem contains multiple test cases!

The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.

The output format consists of N output blocks. There is a blank line between output blocks.


Input

The first line of the input file contains the number N (1 <= N <= 200) - the number of nodes and and M - the number of pipes. The following M lines contain four integer number each - i, j, lij and cij each. There is at most one pipe connecting any two nodes and 0 <= lij <= cij <= 10^5 for all pipes. No pipe connects a node to itself. If there is a pipe from i-th node to j-th, there is no pipe from j-th node to i-th.


Output

On the first line of the output file print YES if there is the way to carry out reactor cooling and NO if there is none. In the first case M integers must follow, k-th number being the amount of liquid flowing by the k-th pipe. Pipes are numbered as they are given in the input file.


Sample Input

2

4 6
1 2 1 2
2 3 1 2
3 4 1 2
4 1 1 2
1 3 1 2
4 2 1 2

4 6
1 2 1 3
2 3 1 3
3 4 1 3
4 1 1 3
1 3 1 3
4 2 1 3


Sample Input

NO

YES
1
2
3
2
1
1



Author: Andrew Stankevich
Source: Andrew Stankevich‘s Contest #1



#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=100005;
const int INF=0x3f3f3f3f;

struct Edge
{
    int to,next,cap,flow;
}edge[1000000];

int Size,Adj[maxn];
int gap[maxn],dep[maxn],pre[maxn],cur[maxn];

void init()
{
    Size=0;
    memset(Adj,-1,sizeof(Adj));
}

void add_edge(int u,int v,int w,int rw=0)
{
    edge[Size].to=v;edge[Size].cap=w;edge[Size].next=Adj[u];
    edge[Size].flow=0;Adj[u]=Size++;
    edge[Size].to=u;edge[Size].cap=rw;edge[Size].next=Adj[v];
    edge[Size].flow=0;Adj[v]=Size++;
}

int sap(int start,int end,int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,Adj,sizeof(Adj));
    
    int u=start;
    pre[u]=-1; gap[0]=N;
    int ans=0;
    
    while(dep[start]<N)
    {
        if(u==end)
        {
            int Min=INF;
            for(int i=pre[u];~i;i=pre[edge[i^1].to])
                if(Min>edge[i].cap-edge[i].flow)
                    Min=edge[i].cap-edge[i].flow;
            for(int i=pre[u];~i;i=pre[edge[i^1].to])
            {
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
            }
            u=start;
            ans+=Min;
            continue;
        }
        bool flag=false;
        int v;
        for(int i=cur[u];~i;i=edge[i].next)
        {
            v=edge[i].to;
            if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if(flag)
        {
            u=v;
            continue;
        }
        int Min=N;
        for(int i=Adj[u];~i;i=edge[i].next)
        {
            if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
        }
        gap[dep[u]]--;
        if(!gap[dep[u]]) return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if(u!=start) u=edge[pre[u]^1].to;
    }
    return ans;
}

int n,m;
int in[maxn],low[maxn];

int main()
{
    int T_T;
    scanf("%d",&T_T);
    while(T_T--)
    {
        /// INIT
        scanf("%d%d",&n,&m);
        init();
        memset(in,0,sizeof(in));
        memset(low,0,sizeof(low));
        int a,b,c,d;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            in[a]-=c;in[b]+=c;
            low[i]=c;
            add_edge(a,b,d-c);
        }
        for(int i=1;i<=n;i++)
        {
            if(in[i]<0) add_edge(i,n+1,-in[i]);
            if(in[i]>0) add_edge(0,i,in[i]);
        }
        sap(0,n+1,n+2);
        bool flag=true;
        for(int i=Adj[0];~i;i=edge[i].next)
        {
            if(edge[i].cap!=edge[i].flow)
            {
                flag=false; break;
            }
        }
        if(flag==true)
        {
            puts("YES");
            for(int i=0;i<m;i++)
            {
                printf("%d\n",edge[2*i].flow+low[i]);
            }
        }
        else
        {
            puts("NO");
        }
    }
    return 0;
}


ZOJ 2314/SGU194 Reactor Cooling