P4177 [CEOI2008] order

题意

给定 \(n\) 个工作,\(m\) 个机器。

每个工作需要若干机器获得 \(s_i\) 的奖励。

机器可以选择租和买。租只能在当前工作内使用。

Sol

考虑在最大权闭合子图上面改改。

发现直接把工作往汇点连买的权值就完事了。

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <queue>
/* #define int long long */
#define pii pair <int, int>
using namespace std;
#ifdef ONLINE_JUDGE

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;

#endif
int read() {
	int p = 0, flg = 1;
	char c = getchar();
	while (c < '0' || c > '9') {
		if (c == '-') flg = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		p = p * 10 + c - '0';
		c = getchar();
	}
	return p * flg;
}
void write(int x) {
	if (x < 0) {
		x = -x;
		putchar('-');
	}
	if (x > 9) {
		write(x / 10);
	}
	putchar(x % 10 + '0');
}

#define fi first
#define se second

const int N = 1e5 + 5, M = 2e7 + 5, inf = 2e9;

namespace G {

array <int, N> fir;
array <int, M> nex, to, cap;
int cnt = 1;
void add(int x, int y, int z) {
	cnt++;
	nex[cnt] = fir[x];
	to[cnt] = y;
	cap[cnt] = z;
	fir[x] = cnt;
}
void _add(int x, int y, int z) {
	add(x, y, z);
	add(y, x, 0);
}

}

namespace Mfl {

array <int, N> cur, dis;
queue <int> q;

bool bfs(pii st) {
	dis.fill(-1), dis[st.fi] = 0;
	q.push(st.fi);
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		for (int i = G::fir[u]; i; i = G::nex[i]) {
			if (!G::cap[i] || ~dis[G::to[i]]) continue;
			dis[G::to[i]] = dis[u] + 1, q.push(G::to[i]);
		}
	}
	return ~dis[st.se];
}

int dfs(int x, int augcd, pii st) {
	if (x == st.se) return augcd;
	int augc = augcd;
	for (int &i = cur[x]; i; i = G::nex[i]) {
		if (!G::cap[i] || dis[G::to[i]] <= dis[x]) continue;
		int flow = dfs(G::to[i], min(augc, G::cap[i]), st);
		augc -= flow;
		G::cap[i] -= flow, G::cap[i ^ 1] += flow;
		if (!augc) break;
	}
	return augcd - augc;
}

int dinic(pii st) {
	int ans = 0;
	while (bfs(st)) {
		copy(G::fir.begin(), G::fir.end(), cur.begin());
		ans += dfs(st.fi, inf, st);
	}
	return ans;
}

}

signed main() {
	int n = read(), m = read();
	int ans = 0;
	pii st = make_pair(n + m + 1, n + m + 2);
	for (int i = 1; i <= n; i++) {
		int x = read(), k = read();
		ans += x;
		while (k--) {
			int u = read(), v = read();
			G::_add(i, n + u, v);
		}
		G::_add(st.fi, i, x);
	}
	for (int i = 1; i <= m; i++)
		G::_add(i + n, st.se, read());
	write(ans - Mfl::dinic(st)), puts("");
	return 0;
}
posted @ 2023-12-13 20:11  cxqghzj  阅读(3)  评论(0编辑  收藏  举报