[TJOI2013]循环格

费用流,

因为要求全部都是回路, 每个点出入度都为1,拆点分别代表出点和入点,剩下不多说。

注意边界可以走 即n->1

/**
 * Problem:Grid
 * Author:Shun Yao
 * Time:2013.5.21
 * Result:Accepted
 * Memo:CostFlow
 */

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

using namespace std;

const long dir[2][4] = {{0, 0, -1, 1}, {-1, 1, 0, 0}}, Maxt = 452;

long s, t, ans, p2[Maxt], q[Maxt], *l, *r;
long d[Maxt];
char inq[Maxt];

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

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

char spfa() {
	static long i;
	static gnode *e;
	memset(d, 0x7f, sizeof d);
	d[s] = 0;
	memset(inq, 0, sizeof inq);
	inq[s] = 1;
	l = q;
	*l = s;
	r = l + 1;
	while (l != r) {
		inq[*l] = 0;
		if (d[*l] == 0x7f7f7f7f) {
			++l;
			if (l == q + Maxt)
				l = q;
			continue;
		}
		for (e = g[*l]; e; e = e->next)
			if (e->f && d[e->v] > d[*l] + e->w) {
				d[e->v] = d[*l] + e->w;
				p1[e->v] = e;
				p2[e->v] = *l;
				if (!inq[e->v]) {
					inq[e->v] = 1;
					*r = e->v;
					++r;
					if (r == q + Maxt)
						r = q;
				}
			}
		++l;
		if (l == q + Maxt)
			l = q;
	}
	if (d[t] == 0x7f7f7f7f)
		return 0;
	ans += d[t];
	for (i = t; i != s; i = p2[i]) {
		p1[i]->f = !p1[i]->f;
		p1[i]->op->f = !p1[i]->op->f;
	}
	return 1;
}

int main() {
	static long n, m, i, j, k, x, y, z;
	static char ch;
	freopen("grid.in", "r", stdin);
	freopen("grid.out", "w", stdout);
	scanf("%ld%ld", &n, &m);
	s = (n * m) << 1;
	t = s + 1;
	for (i = 0; i < n; ++i) {
		for (j = 0; j < m; ++j) {
			add(s, i * m + j, 0);
			add(i * m + j + n * m, t, 0);
			scanf(" %c", &ch);
			switch (ch) {
			case 'L':z = 0;break;
			case 'R':z = 1;break;
			case 'U':z = 2;break;
			case 'D':z = 3;break;
			}
			for (k = 0; k < 4; ++k) {
				x = (i + dir[0][k] + n) % n;
				y = (j + dir[1][k] + m) % m;
				add(i * m + j, x * m + y + n * m, k != z);
			}
		}
	}
	ans = 0;
	while (spfa());
	printf("%ld", ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/hsuppr/p/3091581.html