zoj 2314 (无汇源的可行流)

有上下界的网络流, 关键是怎么把下界体现出来,于是要先判断是否可行。然后在求解最大流.

这题是没有给出源点和汇点的,但是题目中有一个条件就是每个点都满足所有流入的和等于所有流出的和,然后我猜想了一下这题给出的图都是环. 如果有出度为0或入度为0的话就不满足题意的要求。 (这一点坑了我很久才把这题做出来)

然后就是关键的一步怎么建附加网络,并求可行流. 首先如果这个网络流可行那么每条边的下界都是必须满足的,于是这个网络在没开始求之前你就可以把每条边都流过大小为它下界的流。 然后就会存在问题,有些时候经过上述操作这个点的流就不平衡了.  如果这个点最后流入的多,那么可想而知的是这个点流出的边要多往外流一些才可能满足流量平衡。 但是怎么样来表示往外多流出一些呢?   其实也就是流出的边要多流过 之前多的流,就可以设一个源点,从源点向每一个流入多的点加一条边。权值就为这多出来的流;  然后就可以表现出流出边的用途,如果能把这从源点流出的值流掉就说明这个点实际上是已经满足流量平衡了. 同理流出的的建立一个汇点,加一条边到汇点.权为多流出的值。   当所有与源点相关的点满流时, 就说明存在可行流。 因为这样每个点都会满足流量平衡. 

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 <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;

#define N 220
#define INF 0x3fffffff

struct node
{
    int to,b,c,w,next;
}edge[10*N*N];

int cnt,pre[N];
int save[N]; // 记录流入与流出的和,流入为正,流出为负
int n,m;
int s,t;
int nn;
int lv[N],gap[N];

void add_edge(int u,int v,int w)
{
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=pre[u];
    pre[u]=cnt++;
}

int sdfs(int k,int w)
{
    if(k==t) return w;
    int f=0;
    int mi=nn-1;
    for(int p=pre[k];p!=-1;p=edge[p].next)
    {
        int v=edge[p].to;
        if( edge[p].w!=0 )
        {
            if( lv[k]==lv[v]+1 )
            {
                int tmp=sdfs(v,min( edge[p].w,w-f ));
                f+=tmp;
                edge[p].w-=tmp;
                edge[p^1].w+=tmp;
                if(f==w||lv[s]==nn) return f;
            }
            if(lv[v]<mi) mi=lv[v];
        }
    }
    if(f==0)
    {
        gap[lv[k]]--;
        if( gap[lv[k]]==0 )
        {
            lv[s] = nn;
            return f;
        }
        lv[k] = mi+1;
        gap[lv[k]]++;
    }    
    return f;
}

int sap()
{
    int sum=0;
    nn=t+1;
    memset(lv,0,sizeof(lv));
    memset(gap,0,sizeof(gap));
    gap[0]=nn;
    while(lv[s]<nn)
    {
        sum+=sdfs(s,INF);
    }
    return sum;
}
int main()
{
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        int sum=0;
        cnt=0;
        memset(pre,-1,sizeof(pre));
        memset(save,0,sizeof(save));
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            int x,y,b,c;
            scanf("%d%d%d%d",&x,&y,&b,&c);
            edge[cnt].b=b;
            edge[cnt].c=c;
            add_edge(x,y,c-b);
            add_edge(y,x,0);
            save[x]-=b;
            save[y]+=b;
        }
        s=0;
        t=n+1;
        for(int i=1;i<=n;i++)
        {
            if( save[i] > 0 )
            {
                sum+=save[i];
                add_edge(s,i,save[i]);
                add_edge(i,s,0);
            }
            else 
            {
                add_edge(i,t,-save[i]);
                add_edge(t,i,0);
            }
        }
        if(sap()==sum) 
        {
            printf("YES\n");
            for(int i=0;i<m;i++)
            {
                printf("%d\n",edge[2*i].b+edge[2*i+1].w);
            }
        }
        else 
        {
            printf("NO\n");
        }
        printf("\n");
    }
    return 0;
}

 

 

posted @ 2013-02-23 11:07  chenhuan001  阅读(271)  评论(0编辑  收藏  举报