POJ 1149 PIGS
2015-12-07 16:32
609 查看
题意
m个猪圈,n个顾客 依次 购买bi头猪,会到某些猪圈买。每次交易过程如下:
1. 顾客开某几个猪圈的门
2. 卖猪
3. 任意分配这几个猪圈的猪的数量
4. 锁门
猪圈可容纳的猪的数量没有限制
问最多能卖出多少猪?
题解
注意到此题有 依次 ,这个限制而基于 依次 的建图方法,与两个元素是否 相邻 很有关系。
建图如下:
1. s->第一个开某个猪圈的顾客连边,容量为开始猪圈的猪数:(s, u, A[i])
2. 若前后顾客之间有猪圈的重合部分,则连边:(u, v, INF)
3. 每个顾客->t,容量为需求量:(u, t, Need[i])
此时,一条流的意义代表一头猪的销售历程。
事实上,猪圈只是一个载体,在猪圈里交换猪的本质是要满足以后某一个顾客的需求。
所以交换猪的过程可以看做:
1. 顾客A用钥匙开门
2. 顾客A等待下一个与他有重合猪圈的人的到来(注意,期间的人与A是不 相关 的)
3. 顾客A把猪提供给顾客B,并把重合猪圈的钥匙交给B
因为顾客A这个“锁门”可以等到与其 相关 的人来的时候,再进行。在顾客A看来,他与B是 相邻 的
窝巢,n,m读反了qwq。更毒的是:poj上交,这题我写多组数据交上去RE,单组数据WA。。。最后发现的确只有一组。。。弄得我已为是数组开小了。。。
code
#include <algorithm> #include <bitset> #include <cassert> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <iostream> #include <map> #include <queue> #include <set> #include <string> #include <vector> const int INF = 0x3f3f3f3f; const int MAXN = 20010; const int MAXM = 100010; struct Dinic { int n, tot, s, t; int st[MAXN], st0[MAXN]; int lk[MAXM << 1], b[MAXM << 1], f[MAXM << 1]; bool del[MAXM << 1]; int Q[MAXN]; int l, r; int d[MAXN]; void init() { memset(st, 0, sizeof st); tot = 1; } void addedge(int u, int v, int w) { lk[++ tot] = st[u]; b[tot] = v; f[tot] = w; del[tot] = 0; st[u] = tot; lk[++ tot] = st[v]; b[tot] = u; f[tot] = 0; del[tot] = 0; st[v] = tot; } bool BFS() { memset(d, 0, sizeof d); l = r = 0; d[ Q[r ++] = s ] = 1; for (; l != r; ++ l) { int u = Q[l]; for (int i = st[u]; i; i = lk[i]) if (!del[i]) { int v = b[i]; if (f[i] && !d[v]) { d[v] = d[u] + 1; Q[r ++] = v; } } } return d[t]; } int DFS(int u, int a) { if (u == t || a == 0) return a; int flow = 0, df; for (int& i = st0[u]; i; i = lk[i]) if (!del[i]) { int v = b[i]; if (d[v] == d[u] + 1 && (df = DFS(v, std::min(a, f[i])))) { f[i] -= df; f[i^1] += df; a -= df; flow += df; if (a == 0) break; } } return flow; } void solve(int s, int t, int& flow) { this->s = s; this->t = t; while (BFS()) { memcpy< c704 /span>(st0, st, sizeof st0); flow += DFS(s, INF); } } void dt(int e) { del[e] = del[e^1] = 1; } void aug(int s, int t, int& flow) { this->s = s; this->t = t; if (BFS()) { memcpy(st0, st, sizeof st0); flow += DFS(s, 1); } } } solver; const int maxm = 10010; int n, m, s, t; int a[maxm]; int lst[maxm]; bool solve() { if (!(scanf("%d%d", &m, &n) == 2)) return 0; s = 0, t = n+1; solver.init(); for (int i = 1; i <= m; ++ i) lst[i] = s; for (int i = 1; i <= m; ++ i) scanf("%d", &a[i]); for (int i = 1; i <= n; ++ i) { int y, x; scanf("%d", &y); while (y --) { scanf("%d", &x); solver.addedge(lst[x], i, (lst[x] == s ? a[x] : INF)); lst[x] = i; } scanf("%d", &x); solver.addedge(i, t, x); } int flow = 0; solver.solve(s, t, flow); printf("%d\n", flow); return 1; } int main() { // freopen("poj1149.in", "r", stdin); while (solve()); // for(;;); return 0; }
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1002
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points