(点击此处查看原题)

题意分析

给出n个结点,m条管道,每条管道存在最小流量和最大流量,而且每个结点的流入量等于流出流出量,问这n个结点和m条管道能否形成流量循环

解题思路

经典的无源汇有上下边界的可行流问题,因为每条边存在最低流量low和最大流量up,所以每条边都至少有low流量,我们为每个边都设置这样的初始流量,这样我们就可以将所有边的下界变为0,上界变成up-low,相当于消灭了下界,而up-low则表示这条边的容量,和普通最大流问题类似,就将原来有上下边界的边转化为容量为up-low的边

而这类问题是没有源点和汇点的,那么我们再构建一对源点汇点即可。

处理好了上下界问题,我们还需要处理另一个核心问题:每个点的流入量等于流出量,因为我们为每条边分配了初始流量,那么对于每个点,有一个初始的流入流出量之差 a[i] = i 点的初始流入量-i点的初始流出量

1)如果a[i] > 0 ,说明流入量过多,那么将多余的流入量视作由源点流入,即由源点向i建一条容量为a[i]的边

2)如果a[i] < 0 ,说明输出量过多,那么将多余的流出量视作流入汇点的,即由i向汇点建一条容量为 |a[i]| 的边

我们用s_out记录源点的总流出量,如果构建的图中的最大流 max_flow == s_out ,说明流量由s 流入原图再流出至汇点的过程中,没有流量损失,这说明原图是流量循环的,而在求最大流的过程中,我们已经将每条边的容量调整好了,即满足条件,那么每条边的实际流量就是 下界+实际流量

代码区

(因为ZOJ暂时交不了这个题,所以我是用别人的标称对拍很久后,得出的代码,如果ZOJ修复了,我会给出通过评测的代码)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip> #define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + ;
const int Max = 1e5 + ;
const int Max2 = 3e2 + ; struct Edge
{
int to, flow, next;
} edge[Max << ]; int n, m, s, t;
int head[Max], tot;
int dis[Max], cur[Max];
int a[Max]; //记录i在初始流中的流入量-流出量
int in[Max]; //in 记录管道的初始流量,即下界;
int id[Max]; //记录水管i在残余网络中的反向边编号 void init()
{
memset(head, -, sizeof(head));
tot = ;
memset(a,,sizeof(a)); s = ;
t = n + ;
} void add(int u, int v, int flow)
{
edge[tot].to = v;
edge[tot].flow = flow;
edge[tot].next = head[u];
head[u] = tot++;
} bool bfs()
{
memset(dis,-,sizeof(dis));
queue<int>q;
dis[s] = ;q.push(s);
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u] ; i != -;i = edge[i].next)
{
int v = edge[i].to;
if(dis[v] == - && edge[i].flow > )
{
dis[v] = dis[u] + ;
if(v == t) return true;
q.push(v);
}
}
}
return false;
} int dfs(int u,int flow_in)
{
if(u == t) return flow_in;
int flow_out = ;
for(int i = cur[u] ; i != - ; i = edge[i].next)
{
cur[u] = i;
int v = edge[i].to;
if(dis[v] == dis[u] + && edge[i].flow > )
{
int flow = dfs(v,min(flow_in,edge[i].flow));
if(flow == ) continue;
flow_in -= flow;
flow_out += flow;
edge[i].flow -= flow;
edge[i^].flow += flow;
if(flow_in == ) break;
}
}
return flow_out;
} int Dinic(int ans)
{
int sum = ;
while(bfs())
{
for(int i = ; i <= ans ;i ++)
cur[i] = head[i];
sum += dfs(s,inf);
}
return sum;
} int main()
{
#ifdef LOCAL
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
init();
for (int i = , u, v, low, up; i <= m; i++)
{
scanf("%d%d%d%d", &u, &v, &low, &up);
in[i] = low; //该水管的初始流量,下界
a[u] -= low; //该点的流出量
a[v] += low; //该点的流入量
add(u,v,up-low);
add(v,u,); //残余网络
id[i] = tot-;
}
int s_out = ; //记录s的流出量
for(int i = ;i <= n ;i ++)
{
if(a[i] > )
add(s,i,a[i]),add(i,s,),s_out += a[i];
else if(a[i] < )
add(i,t,-a[i]),add(t,i,);
}
int max_flow = Dinic(n+);
if(max_flow == s_out)
{
printf("YES\n");
for(int i = ;i <= m ;i ++)
printf("%d\n",in[i] + edge[id[i]].flow); //加上反边的容量,即为该点相对于下界增加的流量
}
else
{
printf("NO\n");
}
}
return ;
}

ZOJ 2314 (无源汇有上下边界的可行流)的更多相关文章

  1. [Ahoi2014]支线剧情[无源汇有下界最小费用可行流]

    3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1538  Solved: 940[Submit][Statu ...

  2. hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流推断 )

    题意:有n个点和m条有向边构成的网络.每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏全部S到T的路径的费用和 > 毁坏全部T到 ...

  3. ZOJ 2314 无源汇可行流(输出方案)

    Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge The terrorist group leaded by a ...

  4. zoj 3229 有源汇有上下界的最大流模板题

    /*坑啊,pe的程序在zoj上原来是wa. 题目大意:一个屌丝给m个女神拍照.计划拍照n天,每一天屌丝最多个C个女神拍照,每天拍照数不能超过D张,并且给每一个女神i拍照有数量限制[Li,Ri], 对于 ...

  5. Shoot the Bullet ZOJ - 3229 有源汇有上下界的最大流

    /** zoj提交评判不了,所以不知道代码正不正确.思路是应该没问题的.如果有不对的地方,请多指教. 题目:Shoot the Bullet ZOJ - 3229 链接:https://vjudge. ...

  6. [ACdream 1211 Reactor Cooling]无源无汇有上下界的可行流

    题意:无源无汇有上下界的可行流 模型 思路:首先将所有边的容量设为上界减去下界,然后对一个点i,设i的所有入边的下界和为to[i],所有出边的下界和为from[i],令它们的差为dif[i]=to[i ...

  7. SGU 194 Reactor Cooling Dinic求解 无源无汇有上下界的可行流

    题目链接 题意:有向图中有n(1 <= n <= 200)个点,无自环或者环的节点个数至少为3.给定每条边的最小流量和最大流量,问每条边的可行流量为多少? 思路:一般求解的网络流并不考虑下 ...

  8. sgu 194 无源汇有上下界的最大流(最大流模板dinic加优化)

    模板类型的题具体参考国家集训队论文:http://wenku.baidu.com/view/0f3b691c59eef8c75fbfb35c.html 参考博客:http://blog.csdn.ne ...

  9. 【模板】无源汇有上下界可行流(网络流)/ZOJ2314

    先导知识 网络最大流 题目链接 https://vjudge.net/problem/ZOJ-2314 题目大意 多组数据,第一行为数据组数 \(T\). 对于每一组数据,第一行为 \(n,m\) 表 ...

随机推荐

  1. 文件操作(stat)

    /*** stat.c ***/ #include<stdio.h> #include<string.h> #include<sys/stat.h> #includ ...

  2. Python excel文件操作,编程练习题实例七十五

    纯文本文件 student.txt为学生信息, 里面的内容(包括花括号)如下所示: { "1":["张三",150,120,100], "2" ...

  3. xcode6 如何编译64位iOS应用

    原文:http://mobile.51cto.com/hot-412500.htm 随着iPhone5S的推出,大家开始关心5S上所使用的64位CPU A7. 除了关心A7的性能以外,大家还会关心一个 ...

  4. System 源码阅读

    System 属性说明 /** * System 类包含了几个有用的字段和方法,并且不能被实例化. * * @author unascribed * @since 1.0 */ public fina ...

  5. OGG-01201

    OGG-01201 Table of Contents 1. OGG-01201 1.1. 案例1 1.2. 案例2 1 OGG-01201 这种错误,出现的场景之一是 direct load 加载数 ...

  6. Ironic 裸金属实例的部署流程

    目录 文章目录 目录 逻辑架构 部署架构 前提条件 部署流程 iSCSI Deploy UML PXE Deploy Driver Direct Deploy UML IPA Deploy Drive ...

  7. Ceph 客户端的 RPM 包升级问题

    问题 最近想把一个现有的 Ceph 客户端升级为最新的 M 版: [root@overcloud-ovscompute-0 ~]# rpm -qa | grep ceph puppet-ceph-2. ...

  8. 转: 动态加载、移除js、css文件

    function loadjscssfile(filename, filetype){ if (filetype=="js"){ var fileref=document.crea ...

  9. python programming作业11 Qt designer (打地鼠,不是很完美)

     不导包的代码 from PyQt5 import QtCore, QtGui, QtWidgets import sys from PyQt5.QtWidgets import QApplicati ...

  10. dokcer部署code-server web版vscode

    #dokcer部署code-server web版vscode codercom/code-server:latest不支持插件在线安装 codercom/code-server:v2目前为最新版1. ...