_bzoj1061 [Noi2008]志愿者招募【最小费用最大流】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1061

尽管不是mcmf的裸题,但还是保存一下模版叭~

很好的一道建模的题,把变量间的加加减减等效成网络中的流入流量与流出流量,再带上个权,求个最小费用就好,详细题解间此:https://www.byvoid.com/blog/noi-2008-employee/

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 1010, maxm = 10005, maxe = 100000;
const long long inf = 0x3c3c3c3c3c3c3c3cLL;

int n, m, a[maxn], s[maxm], t[maxm], cost[maxm], S, T;
int head[maxn], to[maxe], next[maxe], from[maxe], lb;
long long d[maxn], c[maxn], w[maxe], flow[maxe], cap[maxe];
int p[maxn], que[maxn], head_, tail, h;
bool inq[maxn];

inline bool spfa(long long & co) {
	memset(d, 0x3c, sizeof d);
	head_ = tail = 0;
	memset(inq, 0, sizeof inq);
	que[tail++] = S;
	inq[S] = 1;
	c[S] = inf;
	d[S] = 0;
	while (head_ != tail) {
		h = que[head_++];
		inq[h] = 0;
		if (head_ == T + 3) {
			head_ = 0;
		}
		for (int j = head[h]; j != -1; j = next[j]) {
			if (cap[j] > flow[j] && d[to[j]] > d[h] + w[j]) {
				d[to[j]] = d[h] + w[j];
				c[to[j]] = std::min(c[h], cap[j] - flow[j]);
				p[to[j]] = j;
				if (!inq[to[j]]) {
					que[tail++] = to[j];
					inq[to[j]] = 1;
					if (tail == T + 3) {
						tail = 0;
					}
				}
			}
		}
	}
	if (d[T] == inf) {
		return false;
	}
	co += d[T] * c[T];
	for (int i = T; i != S; i = from[p[i]]) {
		flow[p[i]] += c[T];
		flow[p[i] ^ 1] -= c[T];
	}
	return true;
}
inline long long mcmf(void) {
	long long co = 0;
	while (spfa(co));
	return co;
}

inline void ist(int aa, int ss, long long ww, long long ca) {
	to[lb] = ss;
	from[lb] = aa;
	next[lb] = head[aa];
	head[aa] = lb;
	w[lb] = ww;
	cap[lb] = ca;
	++lb;
	
	to[lb] = aa;
	from[lb] = ss;
	next[lb] = head[ss];
	head[ss] = lb;
	w[lb] = -ww;
	cap[lb] = 0;
	++lb;
}

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 + 2;
	for (int i = 1; i <= n; ++i) {
		scanf("%d", a + i);
	}
	for (int i = 1; i <= m; ++i) {
		scanf("%d%d%d", s + i, t + i, cost + i);
	}
	
	for (int i = 1; i <= n + 1; ++i) {
		if (a[i - 1] - a[i] >= 0) {
			ist(S, i, 0, (long long)(a[i - 1] - a[i]));
		}
		else {
			ist(i, T, 0, (long long)(a[i] - a[i - 1]));
		}
	}
	for (int i = 1; i <= m; ++i) {
		ist(t[i] + 1, s[i], (long long)cost[i], inf);
	}
	for (int i = 1; i <= n; ++i) {
		ist(i, i + 1, 0, inf);
	}
	printf("%lld\n", mcmf());
	return 0;
}

  

posted @ 2016-12-14 20:03  ciao_sora  阅读(194)  评论(0编辑  收藏  举报