ZOJ2314 Reactor Cooling

Posted 大奕哥&VANE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ2314 Reactor Cooling相关的知识,希望对你有一定的参考价值。

题目大意是这样的,给出n个点和m条边,每个边有一个流量的上下界,问是否存在一个循环的流量。这就是典型的无汇源点的上下界网络流,也就是循环流。做法是这样的,首先每条边我们都添加最少的流量,由于要满足流量守恒的条件,即每个点的流出量等于流入量,那么我们尝试进行修改,添加新的流量。我们记录一下每个点流出量与流入量的差,新建虚拟汇点源点,如果一个点流入量大于流出量,那么我们把他连向汇点,反之连向源点(容量都取绝对值),然后原来的m条边流量全部变为上下界的差。这样有源点有汇点的网络流就建出来了,跑一下最大流,如果最大流等于我们源点连出来的所有边的容量之和,那么就是有解的,反之就无解。因为我们新建的网络流源点与汇点的流量之和一定相同(原图上每个边的贡献为0,两两抵消),如果最大流满流意味着我们在每条边流量为下限的时候找到了一条新的流量使得原图的流量守恒,而我们取得是流量的下限,如果此时找不到流量守恒的流量,那么肯定就无解了。 —— by VANE

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=300;
const int M=N*400;
int ss,tt,pre[M],other[M],last[N],l=1,cap[M],low[M];
int n,m,d[N],flow[M],dis[N];
void add(int a,int b,int c)
{
    ++l;pre[l]=last[a];last[a]=l;other[l]=b;cap[l]=c;flow[l]=0;
    swap(a,b);++l;pre[l]=last[a];last[a]=l;other[l]=b;cap[l]=0;flow[l]=0;
}
bool bfs()
{
    memset(dis,0,sizeof dis);
    queue<int> q;
    q.push(ss);
    dis[ss]=1;
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int p=last[u];p;p=pre[p])
        {
            int v=other[p];
            if(!cap[p]||dis[v]) continue;
            dis[v]=dis[u]+1;
            q.push(v);
        }
    }
    if(dis[tt]) return 1;
    return 0;
}
int dfs(int x,int f)
{
    if(x==tt) return f;
    if(f==0) return 0;
    int res=f;
    for(int p=last[x];p;p=pre[p])
    {
        int v=other[p];
        if(dis[v]!=dis[x]+1||!cap[p]) continue;
        if(!res) break;
        int tmp=dfs(v,min(cap[p],res));
        res-=tmp;
        cap[p]-=tmp;
        flow[p]+=tmp;
        cap[p^1]+=tmp;
        flow[p^1]-=tmp;
        if(tmp==0) dis[v]=-1;
    }
    return f-res;
}
int dinic()
{
    int res=0;
    while(bfs()) res+=dfs(ss,1e9);
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        l=1;
        memset(d,0,sizeof d);
        memset(last,0,sizeof last);
        scanf("%d%d",&n,&m);
        ss=n+1;tt=n+2;
        for(int i=1;i<=m;++i)
        {
            int a,b,c;
            scanf("%d%d%d%d",&a,&b,&low[i],&c);
            add(a,b,c-low[i]);
            d[a]+=low[i];
            d[b]-=low[i];
        }
        int tot=0;
        for(int i=1;i<=n;++i)
        {
            if(d[i]<0) add(ss,i,-d[i]);
            else add(i,tt,d[i]),tot+=d[i];
        }
        if(dinic()!=tot) puts("NO");
        else
        {
            puts("YES");
            for(int i=1;i<=m;++i)
            printf("%d\n",flow[i<<1]+low[i]);
        }
    }
}

 

以上是关于ZOJ2314 Reactor Cooling的主要内容,如果未能解决你的问题,请参考以下文章

ZOJ2314:Reactor Cooling——题解

ZOJ_2314_Reactor Cooling_有上下界可行流模板

Reactor Cooling ZOJ - 2314 上下界网络流

zoj 2314 Reactor Cooling (无源汇上下界可行流)

zoj 2314Reactor Cooling

ZOJ2314 Reactor Cooling