SGU 176 Flow construction(有源汇上下界最小流)
Description
176. Flow construction
memory limit per test: 4096 KB
output: standard
The substance cannot be accumulated in the nodes. But it is being produced in the first node with the non-negative speed and being consumed with the same speed in the last node.
You have some subset taken from the set of pipes of this net. You need to start the motion of substance in the net, and your motion must fully fill the pipes of the given subset. Speed of the producing substance in the first node must be minimal.
Calculate this speed and show the scene of substance motion.
Remember that substance can't be accumulated in the nodes of the net.
There are M lines follows: each line contains four integer numbers Ui, Vi, Zi, Ci; the numbers are separated by a space. Ui is the beginning of i-th pipe, Vi is its end, Zi is a capacity of i-th pipe (1<=Zi<=10^5) and Ci is 1 if i-th pipe must be fully filled, and 0 otherwise.
Any pair of nodes can be connected only by one pipe. If there is a pipe from node A to node B, then there is no pipe from B to A. Not a single node is connected with itself.
There is no pipe which connects nodes number 1 and N. Substance can flow only from the beginning of a pipe to its end.
Write M integers in the second line - i-th number ought to be the flow speed in the i-th pipe (numbering of pipes is equal to the input).
If it is impossible to fill the given subset, write "Impossible".
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; const int MAXN = ;
const int MAXE = MAXN * MAXN * ;
const int INF = 0x3fff3fff; struct SAP {
int head[MAXN], gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
int to[MAXE], next[MAXE], flow[MAXE], cap[MAXE];
int n, ecnt, st, ed; void init() {
memset(head, , sizeof(head));
ecnt = ;
} void add_edge(int u, int v, int c) {
to[ecnt] = v; cap[ecnt] = c; flow[ecnt] = ; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; cap[ecnt] = ; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
//printf("%d->%d %d\n", u, v, c);
} void bfs() {
memset(dis, 0x3f, sizeof(dis));
queue<int> que; que.push(ed);
dis[ed] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
++gap[dis[u]];
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(cap[p ^ ] > flow[p ^ ] && dis[v] > n) {
dis[v] = dis[u] + ;
que.push(v);
}
}
}
} int Max_flow(int ss, int tt, int nn) {
st = ss, ed = tt, n = nn;
int ans = , minFlow = INF, u;
for(int i = ; i <= n; ++i) {
cur[i] = head[i];
gap[i] = ;
}
u = pre[st] = st;
bfs();
while(dis[st] < n) {
bool flag = false;
for(int &p = cur[u]; p; p = next[p]) {
int &v = to[p];
if(cap[p] > flow[p] && dis[u] == dis[v] + ) {
flag = true;
minFlow = min(minFlow, cap[p] - flow[p]);
pre[v] = u;
u = v;
if(u == ed) {
ans += minFlow;
while(u != st) {
u = pre[u];
flow[cur[u]] += minFlow;
flow[cur[u] ^ ] -= minFlow;
}
minFlow = INF;
}
break;
}
}
if(flag) continue;
int minDis = n - ;
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(cap[p] > flow[p] && dis[v] < minDis) {
minDis = dis[v];
cur[u] = p;
}
}
if(--gap[dis[u]] == ) break;
++gap[dis[u] = minDis + ];
u = pre[u];
}
return ans;
}
} G; int n, m, a, b, c, d, x;
int f[MAXN], down[MAXE], id[MAXE]; int main() {
scanf("%d%d", &n, &m);
G.init();
int sum = ;
int ss = n + , tt = n + ;
for(int i = ; i <= m; ++i) {
scanf("%d%d%d%d", &a, &b, &c, &d);
if(d == ) {
f[a] -= c;
f[b] += c;
down[i] = c;
//G.add_edge(a, b, 0);
}
else {
id[i] = G.ecnt;
G.add_edge(a, b, c);
}
}
for(int i = ; i <= n; ++i) {
if(f[i] > ) sum += f[i], G.add_edge(ss, i, f[i]);
else G.add_edge(i, tt, -f[i]);
}
sum -= G.Max_flow(ss, tt, tt);
int ans_id = G.ecnt;
G.add_edge(n, , INF);
if(sum == G.Max_flow(ss, tt, tt)) {
printf("%d\n", G.flow[ans_id]);
for(int i = ; i < m; ++i) {
if(down[i]) printf("%d ", down[i]);
else printf("%d ", G.flow[id[i]]);
}
if(down[m]) printf("%d\n", down[m]);
else printf("%d\n", G.flow[id[m]]);
}
else printf("Impossible\n");
return ;
}
顺便放上zhuzeyuan 2006年国家集训队作业对此题的解题报告……
——————————————————————————————————————————————————————————————————————————————————————————————
问题名称:Flow Construction
问题来源:SGU
解决程度:完美解决
问题简述:
N个节点的网络,有一个起点S,和一个终点T,另外有M根有向的管子连接它们。每根管子有单位时间的流量限制,并且其中有些管子必须完全充满(实际流量等于流量限制)。起点处可以制造物质,终点处可以吸收物质,求最小的制造速度(吸收速度),使得流量满足条件。
分析:
仔细分析问题,其实是“有上下界的最小流”。“流量限制”是网络流中的“容量上届”,必须要充满的管道,容量下界等于上界。
翻开了各类书籍,可以找到用附加网求网络最小流的算法。
经典算法:
建立附加源s',和附加汇t'。对每个顶点a,添加一条新弧at',容量设为所有以a为尾的弧的下限之和;对每个顶点a,添加一条新弧s'a,容量设为所有以a为头的弧的下限之和。原图中的边保留,容量设定为上限减去下限。添加一条新弧t->s(顶点n->1),容量无限大。(注,这里没有必要再设置s->t,书上是错的)
求s'到t'的最大流,如果能让所有s'出去的弧都满载,就有解。否则无解。如果有解,再利用t->s求最大流,将流量缩小。
算法质疑:
在附加网,以及流量缩小的地方,该算法容易被引起质疑:
例如如下情况,B->C容量为1,要求被满载。
S-->--A--->--B--->---T
\ /
/\ \/
\C/
如用上述方法,将得到最小流量为0,也就是仅仅出现A->B->C->A一个环的情况,而不是S->A->B->C->A->B->T的流量为1的结果。
但是要注意网络流的定义,其并没有说这种情况不能发生。对于本题,设定S制造速度为0,一开始ABC中间就有物质在不停地运动(题目中没有说不可以)。
流量缩小的过程并不尽如人意,比如:
S--->--T
\ /
/\ \/
\A/
T->A容量为1要求满载。
那么在缩小流量的时候,会把S->T->A->S圈上的S->T删掉,得到流量-1……为什么呢?
因为在网络流的定义中,规定了不能有弧指向S,也不能有弧流出T。我们必须要再设定超级源和超级汇……有没有简便的方法呢?
算法改进:
不缩小流?很容易地,我们找到了许多反例。对前面“标准算法”的思想理解透彻,仔细思考后发现:
t->s(也就是N->1)弧的流量,就是s点的制造速度。因此,只要在t->s的弧上设定费用为1,对附加网求最小费用最大流就可以了。
算法最终改进:
事实上,进行两次最大流即可。
第一次不添加t->s的弧,求最大流。第二次把这条弧填进去,再尝试把s’流出的弧都满载,进行一次最大流。不难证明正确性。
我觉得我的方法适用于所有“上下界的最小流”问题,简单易行,时间复杂度平均意义上更低。
期望得分:满分
——————————————————————————————————————————————————————————————————————————————————————————————
SGU 176 Flow construction(有源汇上下界最小流)的更多相关文章
- SGU 176 Flow construction【有上下界最小流】
正好考到了所以翻一些题来做--猛然发现搞了半个月的网络流却没做两道上下界(不过这种题好像是比较少233) 首先建立超级源汇ss,tt,没限制的边照常连,对于有限制的边(u,v,mn,mx),连接(u, ...
- BZOJ_2502_清理雪道_有源汇上下界最小流
BZOJ_2502_清理雪道_有源汇上下界最小流 Description 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道), ...
- 【Loj117】有源汇上下界最小流(网络流)
[Loj117]有源汇上下界最小流(网络流) 题面 Loj 题解 还是模板题. #include<iostream> #include<cstdio> #include< ...
- hdu3157有源汇上下界最小流
题意:有源汇上下界最小流裸题,主要就是输入要用字符串的问题 #include<bits/stdc++.h> #define fi first #define se second #defi ...
- BZOJ 2502 清理雪道(有源汇上下界最小流)
题面 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机, ...
- BZOJ 2502 清理雪道/ Luogu P4843 清理雪道 (有源汇上下界最小流)
题意 有一个有向无环图,求最少的路径条数覆盖所有的边 分析 有源汇上下界最小流板题,直接放代码了,不会的看dalao博客:liu_runda 有点长,讲的很好,静心看一定能看懂 CODE #inclu ...
- sgu176 有源汇上下界最小流
题意:有一堆点和边,1起点,n终点,某些边有可能必须满流,要求满足条件的最小流 解法:按原图建边,满流的即上下界都是容量,但是这样按有源汇上下界可行流求出来的可能不是最小流,那么我们需要开始建边的时候 ...
- HDU 3157 Crazy Circuits (有源汇上下界最小流)
题意:一个电路板,上面有N个接线柱(标号1~N) 还有两个电源接线柱 + - 然后是 给出M个部件正负极的接线柱和最小电流,求一个可以让所有部件正常工作的总电流. 析:这是一个有源汇有上下界的 ...
- SGU 176.Flow construction (有上下界的最大流)
时间限制:0.5s 空间限制:4M 题意: 有一个由管道组成的网络,有n个节点(n不大于100),1号节点可以制造原料,最后汇集到n号节点.原料通过管道运输.其中有一些节点有管道连接,这些管道都有着最 ...
随机推荐
- 02.将python3作为centos7的默认python命令
博客为日常工作学习积累总结: 由于个人兴趣爱好对python有了解: 1.安装Python3: 参考博客:https://zhuanlan.zhihu.com/p/47868341 安装依赖包: yu ...
- 纯JS实现轮播图特效——详解
<div id="slider"> <div id="sliderImgs"> <img src="img/mi04.j ...
- 集合,ArrayList练习
import java.util.ArrayList; import java.util.Iterator; public class ArrayListTest { public static vo ...
- java中反射的基本使用
fanShe.java package example5;class fanShe{ /*1.应用在一些通用性比较高的代码中. *2.后面学的框架,大多数都是应用框架来实现的. ...
- Linux phpmailer发送邮件失败的解决方法
(本地windows phpmailer发送ok 放到linux发送失败) 原因:linux 通过465端口进行更安全的SMTPS协议发送邮件 windows 是基于smtp 25端口的 因此 可 ...
- linux系统快速安装宝塔
宝塔面板分linux面板和windows面板,安装宝塔linux面板首先要访问宝塔官网查看对应版本进行选择 宝塔面板的安装需要注意的地方有: 1.纯净系统 2.确保是干净的操作系统,没有安装过其它环境 ...
- 学习 Git的使用过程
原文链接: http://www.cnblogs.com/NickQ/p/8882726.html 学习 Git的使用过程 初次使用 git config --global user.name &qu ...
- Python学习笔记六:集合
集合 Set,去重,关系测试:交.并.差等:无序 list_1=set(list_1), type(list_1) list_2=set([xxxxx]) 交集:list_1.intersectin( ...
- linux进程篇 (三) 进程间的通信3 IPC通信
3 IPC通信 用户空间 进程A <----无法通信----> 进程B -----------------|--------------------------------------|- ...
- yii2 shi用modal弹窗 select2搜索框无法使用
在modal使用begin的时候指定options选项的tabindex为false Modal::begin([ // ...... 'options' => [ 'tabindex' =&g ...