_bzoj1497 [NOI2006]最大获利【最大权闭合子图】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1497
保存最大流模版。
选一个用户群,就必须要选对应的两个中转站,这种关系类似“最大全闭合子图”的关系,因此构图,求最小割。
#include <cstdio> #include <cstring> #include <algorithm> const int maxn = 5005, maxm = 50005, maxe = 400000; int n, m, t1, t2, t3, S, T, ans; int head[maxn + maxm], to[maxe], next[maxe], from[maxe], cap[maxe], flow[maxe], lb; int d[maxn + maxm], que[maxn + maxm], head_, tail, h, num[maxn + maxm], p[maxn + maxm]; inline void ist(int aa, int ss, int ca) { to[lb] = ss; from[lb] = aa; next[lb] = head[aa]; head[aa] = lb; cap[lb] = ca; ++lb; to[lb] = aa; from[lb] = ss; next[lb] = head[ss]; head[ss] = lb; cap[lb] = 0; ++lb; } inline int lbl(int i) { int rt = T; for (int j = head[i]; j != -1; j = next[j]) { if (cap[j] > flow[j]) { rt = std::min(rt, d[to[j]]); } } return rt + 1; } inline int fnd(int i) { for (int j = head[i]; j != -1; j = next[j]) { if (d[i] == d[to[j]] + 1 && cap[j] > flow[j]) { return j; } } return -1; } inline int maxflow(void) { int rt = 0, delta; int i = S, j, x; while (d[S] <= T) { j = fnd(i); if (j != -1) { p[to[j]] = j; i = to[j]; if (i == T) { delta = 2147483647; for (; i != S; i = from[p[i]]) { delta = std::min(delta, cap[p[i]] - flow[p[i]]); } for (i = T; i != S; i = from[p[i]]) { flow[p[i]] += delta; flow[p[i] ^ 1] -= delta; } rt += delta; } } else { x = lbl(i); if (--num[d[i]] == 0) { return rt; } ++num[d[i] = x]; if (i != S) { i = from[p[i]]; } } } return rt; } int main(void) { //freopen("in.txt", "r", stdin); memset(head, -1, sizeof head); memset(next, -1, sizeof next); scanf("%d%d", &n, &m); T = n + m + 1; for (int i = 1; i <= n; ++i) { scanf("%d", &t3); ist(S, i, t3); } for (int i = n + 1; i <= n + m; ++i) { scanf("%d%d%d", &t1, &t2, &t3); ans += t3; ist(i, T, t3); ist(t1, i, 0x3c3c3c3c); ist(t2, i, 0x3c3c3c3c); } memset(d, 0x3c, sizeof d); d[T] = 0; que[tail++] = T; while (head_ != tail) { h = que[head_++]; ++num[d[h]]; for (int j = head[h]; j != -1; j = next[j]) { if ((j & 1) && d[to[j]] == 0x3c3c3c3c) { d[to[j]] = d[h] + 1; que[tail++] = to[j]; } } } printf("%d\n", ans - maxflow()); return 0; }