Description

176. Flow construction

time limit per test: 1 sec. 
memory limit per test: 4096 KB
input: standard 
output: standard
You have given the net consisting of nodes and pipes; pipes connect the nodes. Some substance can flow by pipes, and flow speed in any pipe doesn't exceed capacity of this pipe. 
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.
Input
Two positive integer numbers N (1<=N<=100) and M have been written in the first line of the input - numbers of nodes and pipes. 
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.
Output
Write one integer number in the first line of the output - it ought to be the minimal speed of the producing substance in the first node. 
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".
 
题目大意:有n个点,m条有向边,每条有向边有一个容量的上界,有一些变的流量必须为满(即下界=上界),求从1到n的最小流。
思路:像无源无汇上下界可行流那样先建好图,记图的超级源点为SS,超级汇点为TT。先从SS到TT跑一遍最大流,然后加边n→1(即T→S)容量为无穷大,然后再从SS到TT跑一遍最大流,若与SS关联的边满容量,则有解,其中最小流为最后加进去的n→1的边的流量,找边的流量跟无源无汇上下界可行流一样,否则无解。
小证明:第一次跑最大流消掉了环,之后加上T→S的边,我估计是所有的边都只能走T→S这条边来增广了……
PS:之前稍微写错了一点,一直PE,估计它要我输出数字我输出了impossible(这样居然不是WA啊可恶)。
 
 #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(有源汇上下界最小流)的更多相关文章

  1. SGU 176 Flow construction【有上下界最小流】

    正好考到了所以翻一些题来做--猛然发现搞了半个月的网络流却没做两道上下界(不过这种题好像是比较少233) 首先建立超级源汇ss,tt,没限制的边照常连,对于有限制的边(u,v,mn,mx),连接(u, ...

  2. BZOJ_2502_清理雪道_有源汇上下界最小流

    BZOJ_2502_清理雪道_有源汇上下界最小流 Description        滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道), ...

  3. 【Loj117】有源汇上下界最小流(网络流)

    [Loj117]有源汇上下界最小流(网络流) 题面 Loj 题解 还是模板题. #include<iostream> #include<cstdio> #include< ...

  4. hdu3157有源汇上下界最小流

    题意:有源汇上下界最小流裸题,主要就是输入要用字符串的问题 #include<bits/stdc++.h> #define fi first #define se second #defi ...

  5. BZOJ 2502 清理雪道(有源汇上下界最小流)

    题面 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机, ...

  6. BZOJ 2502 清理雪道/ Luogu P4843 清理雪道 (有源汇上下界最小流)

    题意 有一个有向无环图,求最少的路径条数覆盖所有的边 分析 有源汇上下界最小流板题,直接放代码了,不会的看dalao博客:liu_runda 有点长,讲的很好,静心看一定能看懂 CODE #inclu ...

  7. sgu176 有源汇上下界最小流

    题意:有一堆点和边,1起点,n终点,某些边有可能必须满流,要求满足条件的最小流 解法:按原图建边,满流的即上下界都是容量,但是这样按有源汇上下界可行流求出来的可能不是最小流,那么我们需要开始建边的时候 ...

  8. HDU 3157 Crazy Circuits (有源汇上下界最小流)

    题意:一个电路板,上面有N个接线柱(标号1~N)   还有两个电源接线柱  +  - 然后是 给出M个部件正负极的接线柱和最小电流,求一个可以让所有部件正常工作的总电流. 析:这是一个有源汇有上下界的 ...

  9. SGU 176.Flow construction (有上下界的最大流)

    时间限制:0.5s 空间限制:4M 题意: 有一个由管道组成的网络,有n个节点(n不大于100),1号节点可以制造原料,最后汇集到n号节点.原料通过管道运输.其中有一些节点有管道连接,这些管道都有着最 ...

随机推荐

  1. [videos系列]日本的videos视频让男人产生了哪些误解?

    转载自:[videos系列]日本的videos视频让男人产生了哪些误解? 日本的videos视频是每个男人成长过程中都会看的启蒙教育片,也是男人在成年后调剂生活的必需品,但是由于影视作品是艺术的,是属 ...

  2. 『C++』Temp_2018_12_13_Type

    #include <iostream> #include <string> using namespace std; class Object{ public: virtual ...

  3. 第四模块MySQL50题作业,以及由作业引申出来的一些高端玩法

    一.表关系 先参照如下表结构创建7张表格,并创建相关约束                 班级表:class       学生表:student       cid caption grade_id ...

  4. Django学习笔记3-静态文件调用

    1.settings.py 静态文件相关示例代码及说明: # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.c ...

  5. 增强for循环和迭代器

    package example6; import java.util.ArrayList;import java.util.Iterator;import java.util.List; class ...

  6. ORALCE表的约束条件

    一.主键:(PRIMARY KEY) 主键是表中的一列或多列.为表定义主键有如下几个作用: 1.主键包含的列不能输入重复的值,以此来保证一个表的所有行的唯一性: 2.主键也不允许定义此约束的列为NUL ...

  7. Android中的AutoCompleteTextView(随笔提示文本)组件的简单使用

    Android中的随笔提示文本组件AutoCompleteTextView的使用,此组件用于输入文本,然后就会在所配置的适配器中的数据进行查找显示在组件下面. 这里值得注意的是AutoComplete ...

  8. 网页股票期货历史数据(API)

    //[和讯数据] //大商所DCE.郑商所CZCE.上期所SHFE3.中金所CFFEX //期货1分钟线http://webftcn.hermes.hexun.com/ ... I1709&d ...

  9. Elasticsearch 数据操作

    一.新增数据 1.1 随机生成id 语法: POST /索引库名/类型名 { "key1": "value1", "key2": " ...

  10. 第6章 AOP与全局异常处理6.1-6.4 慕课网微信小程序开发学习笔记

    第6章 AOP与全局异常处理 https://coding.imooc.com/learn/list/97.html 目录: 第6章 AOP与全局异常处理6-1 正确理解异常处理流程 13:236-2 ...