[ZOJ2314]Reactor Cooling(无源汇有上下界的可行流)

前端之家收集整理的这篇文章主要介绍了[ZOJ2314]Reactor Cooling(无源汇有上下界的可行流)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

题目描述

传送门

题意:
一个核反应堆的冷却系统有n个结点,有m条单向的管子连接它们,管子内流量有上下界的要求,问能否使液体在整个系统中循环流动。

题解

无源汇有上下界的可行流
建图方法
建立附加源汇st
假设xy有边,下界为l上界为r,那么x->y,r-l
令d(i)表示所有流入i的边的下界和-所有流出i的边的下界和
若d(i)>0,那么s->i,d(i)
若d(i)<0,那么i->t,-d(i)
跑最大流,如果与st相连的边都能满留,就说明所有的下界都满足了,那么一定存在可行流。
流经x->y这条边的实际流量就是反向边的残余流量+这条边的流量下界。

建图的具体证明见论文 《一种简易的方法求解流量有上下界的网络中网络流问题》

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define N 100005
#define inf 1000000000

int T,n,m,x,y,l,r,s,t,maxflow,sum;
int d[N],b[N],pipe[N];
int tot,point[N],nxt[N],v[N],remain[N];
int deep[N],cur[N],last[N],num[N];
queue <int> q;

void clear()
{
    maxflow=sum=0;
    memset(d,0,sizeof(d));
    tot=-1;memset(point,-1,sizeof(point));
    memset(num,sizeof(num));
}
void addedge(int x,int y,int cap)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap;
    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
void bfs(int t)
{
    for (int i=s;i<=t;++i) deep[i]=t;
    deep[t]=0;
    for (int i=s;i<=t;++i) cur[i]=point[i];
    while (!q.empty()) q.pop();
    q.push(t);

    while (!q.empty())
    {
        int now=q.front();q.pop();
        for (int i=point[now];i!=-1;i=nxt[i])
            if (deep[v[i]]==t&&remain[i^1])
            {
                deep[v[i]]=deep[now]+1;
                q.push(v[i]);
            }
    }
}
int addflow(int s,int t)
{
    int now=t,ans=inf;
    while (now!=s)
    {
        ans=min(ans,remain[last[now]]);
        now=v[last[now]^1];
    }
    now=t;
    while (now!=s)
    {
        remain[last[now]]-=ans;
        remain[last[now]^1]+=ans;
        now=v[last[now]^1];
    }
    return ans;
}
void isap(int s,int t)
{
    bfs(t);
    for (int i=s;i<=t;++i) ++num[deep[i]];

    int now=s;
    while (deep[s]<t)
    {
        if (now==t)
        {
            maxflow+=addflow(s,t);
            now=s;
        }

        bool has_find=false;
        for (int i=cur[now];i!=-1;i=nxt[i])
            if (deep[v[i]]+1==deep[now]&&remain[i])
            {
                has_find=true;
                cur[now]=i;
                last[v[i]]=i;
                now=v[i];
                break;
            }

        if (!has_find)
        {
            int minn=t-1;
            for (int i=point[now];i!=-1;i=nxt[i])
                if (remain[i]) minn=min(minn,deep[v[i]]);
            if (!(--num[deep[now]])) break;
            ++num[deep[now]=minn+1];
            cur[now]=point[now];
            if (now!=s) now=v[last[now]^1];
        }
    }
}
int main()
{
    scanf("%d",&T);
    while (T--)
    {
        clear();
        scanf("%d%d",&n,&m);
        s=1,t=n+2;
        for (int i=1;i<=m;++i)
        {
            scanf("%d%d%d%d",&x,&y,&l,&r);
            addedge(1+x,1+y,r-l);pipe[i]=tot;
            d[1+x]-=l;d[1+y]+=l;b[i]=l;
        }
        for (int i=1;i<=n;++i)
            if (d[1+i]>0) addedge(s,1+i,d[1+i]),sum+=d[1+i];
            else if (d[1+i]<0) addedge(1+i,-d[1+i]);
        isap(s,t);
        if (maxflow==sum)
        {
            puts("YES");
            for (int i=1;i<=m;++i)
                printf("%d\n",remain[pipe[i]]+b[i]);
        }
        else puts("NO");
        puts("");
    }
}

猜你在找的React相关文章