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 ...
随机推荐
- 【响应式Web设计实践 #BOOK#】
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- C语言基础课程 第四课 它山之石可以攻玉---C语言数据类型和表达式
1 C语言中的数据类型 1.1 常量 常量就是在程序中不可变化的量 1.1.1 #define #define MAX 10 Define;//定义了一 ...
- excel小技巧-用于测试用例的编号栏:“获取当前单元格的上一格的值+1”=INDIRECT(ADDRESS(ROW()-1,COLUMN()))+1
编写用例的时候使用,经常修改用例的时候会需要增加.删除.修改条目,如果用下拉更新数值的方式会很麻烦. 1.使用ctrl下拉,增删移动用例的时候,需要每次都去拉,万一列表比较长,会很麻烦 2.使用ROW ...
- java常见错误云集与注意事项
1.安装Eclipse时,尽量jdk不要用jre,jdk包含jre j JDK就是Java Development Kit.简单的说JDK是面向开发人员使用的SDK,它提供了Java的开发环境和运行环 ...
- leetcode 栈 括号匹配
https://oj.leetcode.com/problems/valid-parentheses/ 遇到左括号入栈,遇到右括号出栈找匹配,为空或不匹配为空, public class Soluti ...
- typedef用法小结
typedef用法小结- - 注意:本文转自网络,版权归原作者所有. typedef typedef用法小结- - 这两天在看程序的时候,发现很多地方都用到typedef,在结构体定义,还有一些数组等 ...
- AWK调用SHELL,并将变量传递给SHELL
在Shell脚本中调用awk是非常自然和简单的,以前还写过一个关于awk/shell相互传递变量的文章:awk与shell之间的变量传递方法在awk脚本中,如果需要调用shell脚本/命令,则需要使用 ...
- 浅谈qmake之pro、pri、prf、prl文件
浅谈qmake之pro.pri.prf.prl文件 转载自:http://blog.csdn.net/dbzhang800/article/details/6348432 尽管每次和cmake对比起来 ...
- Codeforces 15B Laser
题目链接:点击打开链接 #include<stdio.h> #include<iostream> #include<string.h> #include<se ...
- Python获取当前时间 分类: python 2014-11-08 19:02 132人阅读 评论(0) 收藏
Python有专门的time模块可以供调用. <span style="font-size:14px;">import time print time.time()&l ...