(点击此处查看原题)

题意分析

给出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. 【CUDA 基础】3.5 展开循环

    title: [CUDA 基础]3.5 展开循环 categories: - CUDA - Freshman tags: - 展开归约 - 归约 - 模板函数 toc: true date: 2018 ...

  2. typedef简化

    /*** mystrcat: ***/ #include<stdio.h> #include<string.h> char *mystrcat(char *s1,char *s ...

  3. ansible模块文件操作

    Ansible常用模块文件操作 [root@tiandong etc]# ansible-doc -l   列出ansible所支持的模块 [root@tiandong ~]# ansible-doc ...

  4. 0.spring cloud目录

    1. 微服务架构概述 1.0. 单体架构是什么 1.1. 单体应用架构存在的问题 1.2. 如何解决单体应用架构存在的问题 1.3. 什么是微服务 1.4. 微服务架构的优点与挑战 1.4.1. 微服 ...

  5. flask中models设计

    1. 自关联 class Comment(db.Model): __tablename__ = 'albumy_comment' id = db.Column(db.Integer, primary_ ...

  6. UEFI和GPT

    好就没用linux了,这几天在win8笔记本上用虚拟机装了下,也准备装到硬盘上和win8双系统使用,发现一些概念已经跟不上时代了. 一个是在虚拟机中装的时候,分配了虚拟硬盘分区时,提示选择分区表类型, ...

  7. php phpexcel 读取excel文件数据

    public function readExcel(){ $allPath = '/home/examine\video/list.xls'; \think\Loader::import('exten ...

  8. 使用redis时遇到的问题及解决方法

    最近在向redis中写入数据的时候,报了下面的错误: failed opening the rdb file crontab (in server root dir /etc) for saving ...

  9. Android RecyclerView与ListView比较

    RecyclerView 概述 RecyclerView 集成自 ViewGroup .RecyclerView是Android-support-V7版本中新增的一个Widgets,官方对于它的介绍是 ...

  10. PLSQL报错: ORA-12514:TNS:监听程序当前无法识别连接描述符中请求的服务

    一开始吓尿了,以为自己动着什么东西了把数据库玩坏了,谁知道打开服务发现服务没启动........... 我们要确保数据库服务是启动状态