SGU 176.Flow construction (有上下界的最大流)
时间限制:0.5s
空间限制:4M
题意:
有一个由管道组成的网络,有n个节点(n不大于100),1号节点可以制造原料,最后汇集到n号节点。原料通过管道运输。其中有一些节点有管道连接,这些管道都有着最大的流量限制,其中有一些管道必须充满。求1号节点最小的制造原料速度。如果原料不能运输到n,输出“Impossible”
Solution
第一道有上下界的网络流。从理解不太深刻,wa了很多次后。完全理解了有上下界网络流的算法。
首先,要构造一个伴随网络,由此判断,是否能让所有的下界满足,并连通源汇点。
由于是求最小流,我们需要知道,是否能从汇点找到一条到源点的增广路。使得最大流减小。
这时可能求出负流flow,只要新加一个节点0,添加到汇点的一条容量为-flow的边,即可让负流变为0;
具体的构造方法在程序注释里。
/*
有容量上下界的最大流算法
1)cap(u,v)为u到v的边的容量
2)Gup(u,v)为u到v的边流量上界
3)Glow(u,v)为u到v的边流量下界
4)st(u)代表点u的所有出边的下界之和
5)ed(u)代表点u的所有入边的下界之和
6)S为源点,T为汇点
新网络D的构造方法:
1)加入虚拟源点SS,ST
2)如果边(u,v)的容量cap(u,v)=Gup(u,v)-Glow(u,v)
3)对于每个点v,加入边(SS,v)=ed(v);
4)对于每个点u,加入边(u,ST)=st(u);
5)cap(T,S)=+∞;
6)tflow为所有边的下界之和
求SS到ST的最大流,若最大流不等于tflow,则不存在可行流,此问题无解。
在新网络D中去掉所有与SS,ST相连的边。求最大流。
最后将两个流值相加
最小流,第二次最大流从T到S运行。 */
#include <iostream>
#include <cstdio>
#include <cstring>
#define ms(a,b) memset(a,b,sizeof a)
using namespace std;
const int INF = ;
struct node {
int u, v, c, next;
} edge[INF * INF << ];
int Gup[INF][INF], Glow[INF][INF], st[INF], ed[INF], cap[INF][INF], tflow;
int pHead[INF*INF], SS, ST, S, T, nCnt, ans;
//同时添加弧和反向边, 反向边初始容量为0
void addEdge (int u, int v, int c) {
edge[++nCnt].v = v, edge[nCnt].u = u, edge[nCnt].c = c;
edge[nCnt].next = pHead[u]; pHead[u] = nCnt;
edge[++nCnt].v = u, edge[nCnt].u = v, edge[nCnt].c = ;
edge[nCnt].next = pHead[v]; pHead[v] = nCnt;
}
int SAP (int pStart, int pEnd, int N) {
int numh[INF], h[INF], curEdge[INF], pre[INF];
int cur_flow, flow_ans = , u, neck, i, tmp;
ms (h, ); ms (numh, ); ms (pre, -);
for (i = ; i <= N; i++) curEdge[i] = pHead[i];
numh[] = N;
u = pStart;
while (h[pStart] <= N) {
if (u == pEnd) {
cur_flow = 1e9;
for (i = pStart; i != pEnd; i = edge[curEdge[i]].v)
if (cur_flow > edge[curEdge[i]].c) neck = i, cur_flow = edge[curEdge[i]].c;
for (i = pStart; i != pEnd; i = edge[curEdge[i]].v) {
tmp = curEdge[i];
edge[tmp].c -= cur_flow, edge[tmp ^ ].c += cur_flow;
}
flow_ans += cur_flow;
u = neck;
}
for ( i = curEdge[u]; i != ; i = edge[i].next) {
if (edge[i].v > N) continue; //重要!!!
if (edge[i].c && h[u] == h[edge[i].v] + ) break;
}
if (i != ) {
curEdge[u] = i, pre[edge[i].v] = u;
u = edge[i].v;
}
else {
if ( == --numh[h[u]]) continue;
curEdge[u] = pHead[u];
for (tmp = N, i = pHead[u]; i != ; i = edge[i].next) {
if (edge[i].v > N) continue; //重要!!!
if (edge[i].c) tmp = min (tmp, h[edge[i].v]);
}
h[u] = tmp + ;
++numh[h[u]];
if (u != pStart) u = pre[u];
}
}
return flow_ans;
}
int solve (int n) {
//建立伴随网络
SS = n + , ST = n + ;
for (int i = ; i <= n; i++) {
if (ed[i]) addEdge (SS, i, ed[i]);
if (st[i]) addEdge (i, ST, st[i]);
}
//T到S添加一条无限容量边
addEdge (T, S, 0x7ffffff);
//判断可行流
int tem = SAP (SS, ST, ST);
if (tem != tflow) return -;
else {
edge[nCnt].c = edge[nCnt - ].c = ; //删除S到T的无限容量边
int kkk = SAP (T, S, T);
return ;
}
}
int n, m, x, y, c, sta;
int main() {
/*
建图,前向星存边,表头在pHead[],边计数 nCnt.
S,T分别为源点和汇点
*/
scanf ("%d %d", &n, &m);
nCnt = ;
for (int i = ; i <= m; i++) {
scanf ("%d %d %d %d", &x, &y, &c, &sta);
Gup[x][y] = c;
if (sta) {
Glow[x][y] = c;
st[x] += c, ed[y] += c;
tflow += c;
}
addEdge (x, y, Gup[x][y] - Glow[x][y]);
}
S = , T = n;
ans = ;
if (solve (n) > ) {
for (int i = ; i <= nCnt; i += ) {
if (edge[i].v <= T && edge[i].u == )
ans += Gup[edge[i].u][edge[i].v] - edge[i].c;
if (edge[i].u <= T && edge[i].v == )
ans -= Gup[edge[i].u][edge[i].v] - edge[i].c;
}
if (ans < ) {
S = ;
addEdge (S, , -ans);
ans = ;
SAP (S, T, T);
}
printf ("%d\n", ans);
for (int i = ; i <= * m; i += )
printf ("%d ", Gup[edge[i].u][edge[i].v] - edge[i].c);
}
else puts ("Impossible");
return ;
}
SGU 176.Flow construction (有上下界的最大流)的更多相关文章
- sgu 176 有源汇有上下界的最小流模板题
/*参考博文:http://hi.baidu.com/dragon_eric123/item/82e259200ece744046996282 有上下界的有源最小流 */ #include<st ...
- SGU 176 Flow construction(有源汇上下界最小流)
Description 176. Flow construction time limit per test: 1 sec. memory limit per test: 4096 KB input: ...
- Flow construction SGU - 176 有源汇有上下界最小流 二分法和回流法
/** 题目:Flow construction SGU - 176 链接:https://vjudge.net/problem/SGU-176 题意: 有源汇有上下界的最小流. 给定n个点,m个管道 ...
- sgu 176 Flow construction(有源汇的上下界最小流)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025 [模型] 有源汇点的上下界最小流.即既满足上下界又满足 ...
- SGU 176 Flow construction (有源有汇有上下界最小流)
题意:给定 n 个点,m 条有向边,如果有向边的标号是1的话,就表示该边的上界下界都为容量 ,如果有向边的标号为0的哈,表示该边的下界为0,上界为容量 ,现在问,从 1 到 n 的最小流是多少,并输出 ...
- SGU 176 Flow construction【有上下界最小流】
正好考到了所以翻一些题来做--猛然发现搞了半个月的网络流却没做两道上下界(不过这种题好像是比较少233) 首先建立超级源汇ss,tt,没限制的边照常连,对于有限制的边(u,v,mn,mx),连接(u, ...
- sgu 194 无源汇有上下界的最大流(最大流模板dinic加优化)
模板类型的题具体参考国家集训队论文:http://wenku.baidu.com/view/0f3b691c59eef8c75fbfb35c.html 参考博客:http://blog.csdn.ne ...
- HDU Destroy Transportation system(有上下界的可行流)
前几天正看着网络流,也正研究着一个有上下界的网络流的问题,查看了很多博客,觉得下面这篇概括的还是相当精确的: http://blog.csdn.net/leolin_/article/details/ ...
- 【UVALive - 5131】Chips Challenge(上下界循环费用流)
Description A prominent microprocessor company has enlisted your help to lay out some interchangeabl ...
随机推荐
- StringBuilder字符串缓冲区
JDK1.5出现StringBuiler:构造一个其中不带字符的字符串生成器,初始容量为 16 个字符.该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候( ...
- Bzoj 2241: [SDOI2011]打地鼠 暴力,枚举,贪心
2241: [SDOI2011]打地鼠 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1022 Solved: 651[Submit][Status ...
- Linq to sql语法
LINQ to SQL语句(1)之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子 ...
- Java 执行jar linux 实例
需求:通过执行jar的方式 ,把某个文件路径下的用户数据同步到redis 1.main 函数 public class Main { private static Logger logger = Lo ...
- C#截取指定字符串函数
本文转载:http://www.cnblogs.com/liufei88866/archive/2012/05/12/2497395.html 一.通过函数方式进行获取. public string ...
- HTML5事件——contextmenu 隐藏鼠标右键菜单
在window中单击右键或在Mac中Ctrl+单击时会触发contextmenu事件,通过取消其默认动作能够提供自己定义菜单. 首先先写一个自己的菜单: <style> ul, li { ...
- 树莓派做AP发射wifi(RTL8188CUS芯片) 分类: shell ubuntu Raspberry Pi 2014-11-29 01:25 822人阅读 评论(0) 收藏
最近在做一个项目,需要用树莓派作为AP发射wifi,对比cubieboard,树莓派的配置容易得多,而且支持也更多. 较为官方的介绍配置为无线热点的文章莫过于这一篇<RPI-Wireless-H ...
- QStandardItemModel角色控制及QTreeView加入不同的右键菜单
1.概述 QTreeView最长用的一个功能就是作为导航栏,像vs里的项目结构树,word的文档结构图,资源管理器的文档结构,等等都是利用树形结构组织的,在前面已经讲述了Qt中使用标准化项目模型QSt ...
- C++中的术语
1 声明式:所谓声明式是告诉编译器某个东西的名称和类型,但忽略细节.下面都是声明式: extern int x; //对象(object)声明式 记住:变量的声明加extern关键字 std::siz ...
- 用 Qt 中的 QDomDocument类 处理 XML 文件(下)
QDomDocument doc; 1).创建根节点:QDomElement root = doc.documentElement("rootName " ); 2).创建元素 ...