sgu176 Flow Construction【有源汇有上下界最小流】
2015-12-18 01:03
393 查看
同样是模板题。
首先将有源汇转换为无源汇,假设原来的源汇为st,我们加入的源汇为ST,那么我们应该从t到s连一条流量为+∞的边,使原来的st满足收支平衡,退化为普通节点。
分离必要边和其他边,从S到T跑最大流,所有与源或者汇相连的边都流满则证明有解。
去掉t到s容量为+∞的边,去掉必要边,从t到s跑最大流。
把得到的答案相减即可。
如果我们得到的答案是负的,那么说明它内部t到s连成了环,那么我们加上S到s容量为-ans的边,跑S到t的最大流,这样所有的边的流量应该就是0,再加上流量下界即为答案。
View Code
首先将有源汇转换为无源汇,假设原来的源汇为st,我们加入的源汇为ST,那么我们应该从t到s连一条流量为+∞的边,使原来的st满足收支平衡,退化为普通节点。
分离必要边和其他边,从S到T跑最大流,所有与源或者汇相连的边都流满则证明有解。
去掉t到s容量为+∞的边,去掉必要边,从t到s跑最大流。
把得到的答案相减即可。
如果我们得到的答案是负的,那么说明它内部t到s连成了环,那么我们加上S到s容量为-ans的边,跑S到t的最大流,这样所有的边的流量应该就是0,再加上流量下界即为答案。
#include <bits/stdc++.h> #define rep(i, a, b) for (int i = a; i <= b; i++) #define drep(i, a, b) for (int i = a; i >= b; i--) #define REP(i, a, b) for (int i = a; i < b; i++) #define mp make_pair #define pb push_back #define clr(x) memset(x, 0, sizeof(x)) #define xx first #define yy second using namespace std; typedef long long i64; typedef pair<int, int> pii; const int inf = ~0U >> 1; const i64 INF = ~0ULL >> 1; //****************************** const int maxn = 105, maxm = 10105; struct Ed { int u, v, nx, c; Ed() {} Ed(int _u, int _v, int _nx, int _c) : u(_u), v(_v), nx(_nx), c(_c) {} } E[maxm << 1]; int G[maxn], edtot = 1; void addedge(int u, int v, int c) { E[++edtot] = Ed(u, v, G[u], c); G[u] = edtot; E[++edtot] = Ed(v, u, G[v], 0); G[v] = edtot; } int level[maxn], S, T; bool bfs(int s, int t) { static int que[maxn]; int qh(0), qt(0); clr(level); level[que[++qt] = s] = 1; while (qh != qt) { int x = que[++qh]; if (qh == maxn - 1) qh = 0; for (int i = G[x]; i; i = E[i].nx) if (E[i].c && !level[E[i].v]) { level[que[++qt] = E[i].v] = level[x] + 1; if (qt == maxn - 1) qt = 0; } } return !!level[t]; } int dfs(int u, int rm, int t) { if (u == t) return rm; int rm1 = rm; for (int i = G[u]; i; i = E[i].nx) { if (E[i].c && level[E[i].v] == level[u] + 1) { int flow = dfs(E[i].v, min(E[i].c, rm), t); E[i].c -= flow, E[i ^ 1].c += flow; if ((rm -= flow) == 0) break; } } if (rm1 == rm) level[u] = 0; return rm1 - rm; } int l[maxm], in[maxn]; int main() { int n, m; scanf("%d%d", &n, &m); rep(i, 1, m) { int x, y, a, b; scanf("%d%d%d%d", &x, &y, &a, &b); l[i] = a * b; if (b) in[y] += a, in[x] -= a; addedge(x, y, a - a * b); } S = n + 1, T = n + 2; int sum(0); rep(i, 1, n) { if (in[i] > 0) sum += in[i]; if (in[i] > 0) addedge(S, i, in[i]); else addedge(i, T, -in[i]); } addedge(n, 1, 0x3f3f3f3f); while (bfs(S, T)) sum -= dfs(S, 0x3f3f3f3f, T); if (sum) { puts("Impossible"); return 0; } int ans = E[edtot].c; E[edtot].c = E[edtot ^ 1].c = 0; int tmp(0); while (bfs(n, 1)) tmp += dfs(n, 0x3f3f3f3f, 1); ans -= tmp; if (ans < 0) { addedge(S, 1, -ans); while (bfs(S, n)) dfs(S, 0x3f3f3f3f, n); ans = 0; } printf("%d\n", ans); rep(i, 1, m) { printf(i == 1 ? "%d" : " %d", E[(i << 1) ^ 1].c + l[i]); } puts(""); return 0; }
View Code
相关文章推荐
- SAP Sybase IQ EVENT Each time a scheduled event handler is completed
- Beta--项目冲刺第七天
- Samba服务学习报错总结
- Beta--项目冲刺第六天
- 格式化字符串长度,超出部分显示省略号,区分汉字跟字母
- android面试题总结
- 系统初始化时是根据什么来识别硬盘设备的?
- Leetcode: Rectangle Area
- 今天同事周斌在预生产环境的服务器上犯了一个致命的错误
- 部署和调优 1.9 samba 部署和优化-3
- 张国祥老师应邀在浙江衢州讲授流程建设与优化课程
- 宁波麒麟贸易集团公司连续三天举办流程管理知识竞赛
- 终于用ADB连上平板了
- 【Beta阶段】第六次Scrum Meeting!
- Winform自定义控件—Button(上)
- Java 初始化与清理
- WordPress升级错误:class-wp-filesystem-direct.php on line 122
- Swift项目兼容Objective-C问题汇总
- KMP字符串查找算法
- [jquery]高级篇--标签选择