[HNOI2013]切糕

一眼最小割。

主要是高度差不超过d的处理。

把(x, y, z) 和 (x - d, y + dir, z + dir) 连边即可,

花一下图就理解了。

/**
 * Problem:[HNOI2013]-D2P3
 * Author:Shun Yao
 * Time:2013.5.29
 * Result:Accepted
 * Memo:MaxFlow
 */

#include <cstring>
#include <cstdlib>
#include <cstdio>

const long Maxt = 65605, inf = 0x7f7f7f7f;

long h[Maxt], p2[Maxt], sum[Maxt], s, t;

long min(long x, long y) {
	return x < y ? x : y;
}

class gnode {
public:
	long v, f, c;
	gnode *op, *next;
	gnode() {}
	~gnode() {}
	gnode(long V, long F, long C, gnode *o, gnode *ne):v(V), f(F), c(C), op(o), next(ne) {}
} *g[Maxt], *now[Maxt], *p1[Maxt];

void add(long x, long y, long c) {
	g[x] = new gnode(y, 0, c, 0, g[x]);
	g[y] = new gnode(x, 0, 0, g[x], g[y]);
	g[x]->op = g[y];
}

long Q[Maxt], *L, *R;
void heights() {
	gnode *e;
	memset(h, -1, sizeof h);
	memset(sum, 0, sizeof sum);
	sum[h[t] = 0] = 1;
	R = (L = &(*Q = t)) + 1;
	while (L != R) {
		for (e = g[*L]; e; e = e->next)
			if (h[e->v] == -1) {
				++sum[h[e->v] = h[*L] + 1];
				*(R++) = e->v;
			}
		++L;
	}
}

void Sap() {
	long i, ans, wt, w;
	char f;
	gnode *e;
	heights();
	for (i = 0; i <= t; ++i) {
		now[i] = g[i];
		p1[i] = 0;
		p2[i] = -1;
	}
	ans = 0;
	i = s;
	while (h[s] < t) {
		f = 0;
		for (e = now[i]; e; e = e->next)
			if (e->c > e->f && h[i] == h[e->v] + 1) {
				now[i] = e;
				p1[e->v] = e;
				p2[e->v] = i;
				i = e->v;
				if (i == t) {
					wt = inf;
					for (w = t; w != s; w = p2[w])
						wt = min(wt, p1[w]->c - p1[w]->f);
					for (w = t; w != s; w = p2[w]) {
						p1[w]->f += wt;
						p1[w]->op->f -= wt;
					}
					ans += wt;
					i = s;
				}
				f = 1;
				break;
			}
		if (!f) {
			w = t;
			for (e = g[i]; e; e = e->next)
				if (e->c > e->f && w > h[e->v]) {
					w = h[e->v];
					now[i] = e;
				}
			++sum[w == t ? w : ++w];
			if (!(--sum[h[i]]))
				break;
			h[i] = w;
			if (i != s)
				i = p2[i];
		}
	}
	printf("%ld", ans);
}

#define ai(x, y, z) (((x) * p + (y) - 1) * q + (z) - 1)
int main() {
	long p, q, r, d, i, j, k, a;
	freopen("d2p3.in", "r", stdin);
	freopen("d2p3.out", "w", stdout);
	scanf("%ld%ld%ld%ld", &p, &q, &r, &d);
	t = (s = ai(r, p, q) + 1) + 1;
	for (i = 1; i <= r; ++i)
		for (j = 1; j <= p; ++j)
			for (k = 1; k <= q; ++k) {
				scanf("%ld", &a);
				add(ai(i - 1, j, k), ai(i, j, k), a);
			}
	for (i = d + 1; i < r; ++i)
		for (j = 1; j <= p; ++j)
			for (k = 1; k <= q; ++k) {
				if (j > 1)
					add(ai(i, j, k), ai(i - d, j - 1, k), inf);
				if (j < p)
					add(ai(i, j, k), ai(i - d, j + 1, k), inf);
				if (k > 1)
					add(ai(i, j, k), ai(i - d, j, k - 1), inf);
				if (k < q)
					add(ai(i, j, k), ai(i - d, j, k + 1), inf);
			}
	for (j = 1; j <= p; ++j)
		for (k = 1; k <= q; ++k) {
			add(s, ai(0, j, k), inf);
			add(ai(r, j, k), t, inf);
		}
	Sap();
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/hsuppr/p/3105918.html