ZOJ 2314 (无源汇有上下边界的可行流)
题意分析
给出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 (无源汇有上下边界的可行流)的更多相关文章
- [Ahoi2014]支线剧情[无源汇有下界最小费用可行流]
3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1538 Solved: 940[Submit][Statu ...
- hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流推断 )
题意:有n个点和m条有向边构成的网络.每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏全部S到T的路径的费用和 > 毁坏全部T到 ...
- ZOJ 2314 无源汇可行流(输出方案)
Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge The terrorist group leaded by a ...
- zoj 3229 有源汇有上下界的最大流模板题
/*坑啊,pe的程序在zoj上原来是wa. 题目大意:一个屌丝给m个女神拍照.计划拍照n天,每一天屌丝最多个C个女神拍照,每天拍照数不能超过D张,并且给每一个女神i拍照有数量限制[Li,Ri], 对于 ...
- Shoot the Bullet ZOJ - 3229 有源汇有上下界的最大流
/** zoj提交评判不了,所以不知道代码正不正确.思路是应该没问题的.如果有不对的地方,请多指教. 题目:Shoot the Bullet ZOJ - 3229 链接:https://vjudge. ...
- [ACdream 1211 Reactor Cooling]无源无汇有上下界的可行流
题意:无源无汇有上下界的可行流 模型 思路:首先将所有边的容量设为上界减去下界,然后对一个点i,设i的所有入边的下界和为to[i],所有出边的下界和为from[i],令它们的差为dif[i]=to[i ...
- SGU 194 Reactor Cooling Dinic求解 无源无汇有上下界的可行流
题目链接 题意:有向图中有n(1 <= n <= 200)个点,无自环或者环的节点个数至少为3.给定每条边的最小流量和最大流量,问每条边的可行流量为多少? 思路:一般求解的网络流并不考虑下 ...
- sgu 194 无源汇有上下界的最大流(最大流模板dinic加优化)
模板类型的题具体参考国家集训队论文:http://wenku.baidu.com/view/0f3b691c59eef8c75fbfb35c.html 参考博客:http://blog.csdn.ne ...
- 【模板】无源汇有上下界可行流(网络流)/ZOJ2314
先导知识 网络最大流 题目链接 https://vjudge.net/problem/ZOJ-2314 题目大意 多组数据,第一行为数据组数 \(T\). 对于每一组数据,第一行为 \(n,m\) 表 ...
随机推荐
- 【CUDA 基础】2.3 组织并行线程
title: [CUDA 基础]2.3 组织并行线程 categories: CUDA Freshman tags: Thread Block Grid toc: true date: 2018-03 ...
- 无法连接虚拟设备 ide1:0
问题: 启动vmware之后,发现出现无法连接 ide 1:0. 网络查找之后,发现是之前挂载的iso镜像找不到了. 原因: 我把iso镜像放到其他位置. 解决: 指定iso文件的位置. 参考:htt ...
- hbase数据导入
hbase数据导入: 参考http://blog.csdn.net/hua840812/article/details/7414875,在把代码copy下来后,发现运行总是报错: java.io.IO ...
- [CSP-S模拟测试]:那一天她里我而去(堆优化Dijkstra)
题目传送门(内部题3) 输入格式 每个测试点有多组测试数据.第一行有一个正整数T表示数据组数.接下来对于每组数据,第一行有两个正整数n,m分别代表图的点数和边数.接下来有m行,每行三个整数u,v,d表 ...
- [题解] [ZJOI2014] 力
题面 题解 恩, 我们首先有这两个关系 \[ \displaystyle\begin{aligned} F_j &= \sum_{i < j}\frac{q_iq_j}{(i - j)^ ...
- 修复Long类型太长转为JSON格式的时候出错的问题
这边项目要求ID是自动生成的20位Long型数字 但是实际中应用的时候回发生一种问题就是,查询的时候debug的时候数据都正常,但是返回前端的时候就会发现,数据错误了. 大体就是类似于下面的这种情况. ...
- STL -- heap结构及算法
STL -- heap结构及算法 heap(隐式表述,implicit representation) 1. heap概述 : vector + heap算法 heap并不归属于STL容器组件,它是个 ...
- MyBatis Mapper Demo
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-/ ...
- python中日志logging模块的性能及多进程详解
python中日志logging模块的性能及多进程详解 使用Python来写后台任务时,时常需要使用输出日志来记录程序运行的状态,并在发生错误时将错误的详细信息保存下来,以别调试和分析.Python的 ...
- 【转】hbase meta表修复
[From]https://www.iteye.com/blog/blackproof-2052898 meta表修复一 查看hbasemeta情况 hbase hbck .重新修复hbase met ...