zoj2314(有上下界的网络流)

传送门:Reactor Cooling

题意:给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质。并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li。

分析:最大流默认的下界为0,而这里的下界却不为0,所以我们要进行再构造让每条边的下界为0,这样做是为了方便处理。对于每根管子有一个上界容量up和一个下界容量low,我们让这根管子的容量下界变为0,上界为up-low。可是这样做了的话流量就不守恒了,为了再次满足流量守恒,即每个节点"入流=出流”,我们增设一个超级源点vs和一个超级终点vt。我们开设一个数组Mi来记录每个节点的流量情况。

Mi=in[i](i节点所有入流下界之和)-out[i](i节点所有出流下界之和)。

当Mi大于0的时候,vs到i连一条流量为Mi的边。

当Mi小于0的时候,i到vt连一条流量为-Mi的边。

最后对(vs,vt)求一次最大流即可,当所有附加边全部满流时(即maxflow==所有Mi>0之和),有可行解。

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <limits.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 410
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
inline int read()
{
    char ch=getchar();int x=0,f=1;
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int n,m,vs,vt,tot;
int pre[N],cur[N],h[N],q[N],in[N],out[N];
struct edge
{
    int u,v,w,next;
    edge() {}
    edge(int u,int v,int w,int next):u(u),v(v),w(w),next(next) {}
} e[N*N];
void addedge(int u,int v,int w)
{
    e[tot]=edge(u,v,w,pre[u]);
    pre[u]=tot++;
    e[tot]=edge(v,u,0,pre[v]);
    pre[v]=tot++;
}
void init()
{
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    memset(pre,-1,sizeof(pre));
    tot=0;
}

/*******************dinic************************/
int bfs()
{
    int head=0,tail=1;
    memset(h,-1,sizeof(h));
    q[0]=vs;h[vs]=0;
    while(head!=tail)
    {
        int u=q[head++];
        for(int i=pre[u];~i;i=e[i].next)
        {
            int v=e[i].v,w=e[i].w;
            if(w&&h[v]==-1)
            {
                h[v]=h[u]+1;
                q[tail++]=v;
            }
        }
    }
    return h[vt]!=-1;
}

int dfs(int u,int flow)
{
    if(u==vt)return flow;
    int used=0;
    for(int i=cur[u];~i;i=e[i].next)
    {
        int v=e[i].v,w=e[i].w;
        if(h[v]==h[u]+1)
        {
            w=dfs(v,min(flow-used,w));
            e[i].w-=w;e[i^1].w+=w;
            if(e[i].w)cur[u]=i;
            used+=w;
            if(used==flow)return flow;
        }
    }
    if(!used)h[u]=-1;
    return used;
}
int dinic()
{
    int res=0;
    while(bfs())
    {
        for(int i=vs;i<=vt;i++)cur[i]=pre[i];
        res+=dfs(vs,inf);
    }
    return res;
}
/********************dinic***********************/
int u,v,w;
int low[N*N],sum;
void build()
{
    n=read();m=read();
    vs=0;vt=n+1;sum=0;
    for(int i=0;i<m;i++)
    {
        u=read();v=read();
        low[i]=read();w=read();
        addedge(u,v,w-low[i]);
        in[v]+=low[i];out[u]+=low[i];
    }
    for(int i=1;i<=n;i++)
    {
        if(in[i]>out[i])
        {
            sum+=in[i]-out[i];
            addedge(vs,i,in[i]-out[i]);
        }
        else addedge(i,vt,out[i]-in[i]);
    }
}
void solve()
{
    int maxflow=dinic();
    if(maxflow<sum)puts("NO");
    else
    {
        puts("YES");
        for(int i=0;i<m;i++)
        {
            printf("%d\n",low[i]+e[(i<<1)^1].w);
        }
    }
    puts("");
}
int main()
{
    int T;
    T=read();
    while(T--)
    {
        init();
        build();
        solve();
    }
}

时间: 2024-12-31 10:11:52

zoj2314(有上下界的网络流)的相关文章

BZOJ 2406 二分+有上下界的网络流判定

思路: 求出每行的和  sum_row 每列的和   sum_line 二分最后的答案mid S->i  流量[sum_row[i]-mid,sum_row[i]+mid] i->n+j 流量[L,R] n+j->T 流量 [sum_line[i]-mid,sum_line[i]+mid] 套用有上下界的网络流 判一下就好了.. 这是道有上下界网络流的裸题 //By SiriusRen #include <queue> #include <cstdio> #inc

有上下界的网络流2-有源汇带上下界网络流ZOJ3229

ZOJ3229题目大意:一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝可以和C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照:否则输出-1. 解题思路:        1.增设一源点st,汇点sd,st到第i天连一条上界为Di下界为0的边,每个女神到汇点连一条下界为Gi上界为正无穷的边,对于每一天,当天到第i个女孩连一条[Li,Ri]的边.        2.

有上下界的网络流1-无源汇带上下界网络流SGU194

今天开始啃网络流了.对于求解无源汇带上下界的网络流,我们可以这样建图:建图模型:         以前写的最大流默认的下界为0,而这里的下界却不为0,所以我们要进行再构造让每条边的下界为0,这样做是为了方便处理.对于每根管子有一个上界容量up和一个下界容量low,我们让这根管子的容量下界变为0,上界为up-low.可是这样做了的话流量就不守恒了,为了再次满足流量守恒,即每个节点"入流=出流",我们增设一个超级源点st和一个超级终点sd.我们开设一个数组du[]来记录每个节点的流量情况.

poj_2396 有上下界的网络流

题目大意 一个mxn的矩阵,给出矩阵中每一行的和sh[1,2...m]以及每一列的数字的和目sv[1,2...n],以及矩阵中的一些元素的范围限制,比如a[1][2] > 1, a[2][3] < 4, a[3][3] = 10等等,且要求矩阵中的每个元素值非负.求出,是否存在满足所有给出的限制条件的矩阵,若存在输出. 题目分析 这么多限制条件..开始只能想到暴力解法+剪枝.这他妈得需要多大的脑洞才能无中生有的想到网络流解法? 不过,给出网络流的想法之后发现采用网络流解法确实很合理,很简单(唯

ZOJ 2314 Reactor Cooling 带上下界的网络流

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题意: 给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质. 并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li. 求的是最大流. 很久之前就看了带上下界的网络流,一直没看懂

【网络流补全计划】Part.Ⅲ有上下界的网络流

本来心情就非常糟糕调月下毛景树把我最后一点写代码的心情调没了 放弃 开始补全网络流. 之前学了普通最大流,那么现在开始补有上下界的网络流. 在普通最大流中,网络里的每一条边都只有流量的上界即边的容量,而引入上下界网络流之后,每个边不但有一个容量,还有一个流量下界. 我们令B(u,v)表示边(u,v)的下界.于是我们可以有表达式: B(u,v)≤f(u,v)≤C(u,v) 有这个式子可以得到 0≤f(u,v)≤C(u,v)?B(u,v) 至此,我们可以将有上下界的网络流分为几种问题来对待,接下来就

SGU 194. Reactor Cooling(无源汇有上下界的网络流)

时间限制:0.5s 空间限制:6M 题意: 显然就是求一个无源汇有上下界的网络流的可行流的问题 Solution: 没什么好说的,直接判定可行流,输出就好了 code /* 无汇源有上下界的网络流 */ #include <iostream> #include <cstring> #define ms(a,b) memset(a,b,sizeof a) using namespace std; const int MAXN = 209; struct node { int u, v

ZOJ 2314 有上下界的网络流

点击打开链接 题意:给定m条边和n个节点,每条边最少的流量和最多的流量,保证每个节点的出入流量和相等,问可以形成吗,可以则输出每条边的流量 思路:一道有上下界的网络流,因为有下界,说明我们每条边必须跑大于等于下界的流量,那我们可以转化一下,将下界设为必要边,也就是我们肯定会跑的边,而且这道题是没有源点和汇点的,所以我们要加这两个点,而对于一条边,a,b,low,high,我们a->b连的流量为high-low,a->T为low,S->b为low,跑最大流,如果满流则方案成功,找边的流量输

关于流量有上下界的网络流问题的求解

之前涉及到的网络流问题,每条弧的容量下限都是0,上限都是C.而在流量有上下界的网络流问题中,每条弧有一个流量下界low,还有一个上界up. 对于这样的问题,一般都三类: 1.没有源点和汇点的有上下界的网络最大流问题 2.有源点和汇点的有上下界的网络最大流问题 3.有源点和汇点的有上下界的网络最小流问题 第一类问题: (没有源点和汇点的有上下界的网络最大流问题) [1]我们需要构造一个伴随网络,首先建立一个附加源点SS和一个附加汇点TT: [2]对于原网络中的每一个顶点Vi,在伴随网络中加一条新的

有上下界的网络流

解决上下界网络流的一般思路: 解决这类问题的关键是如何去掉下界带来的麻烦.下面的哈工大出版的<图论及应用>里的思路. 1.网络的必要弧和构建附加网络 前一个数是下界,后一个数是上界. 下面的边是必要弧,其权值为下界.上面的边容量为上界与下界的差. 添加附加源点Y,附加汇点X (别弄错了) ,<X , Y>为的权值正无穷.对于必要弧<u , v>,添加<u,Y>,<Y,v>,容量为必要弧的容量. 删除<X, Y>,添加<T, S&