【BZOJ2437】【NOI2011】兔兔与蛋蛋

【题目链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	45
#define MAXK	1005
#define MAXP	1605
#define INF	1e9
struct edge {int dest, flow; unsigned pos; };
vector <edge> a[MAXP];
char mp[MAXN][MAXN];
bool visited[MAXN][MAXN];
unsigned curr[MAXP];
int d[MAXP];
int n, m, homex, homey, s, t;
bool bfs() {
	static int q[MAXN];
	int l = 0, r = 0;
	memset(d, 0, sizeof(d));
	q[0] = s; d[s] = 1;
	while (l <= r) {
		int tmp = q[l];
		for (unsigned i = 0; i < a[tmp].size(); i++)
			if (a[tmp][i].flow && d[a[tmp][i].dest] == 0) {
				q[++r] = a[tmp][i].dest;
				d[q[r]] = d[tmp] + 1;
			}
		l++;
	}
	return d[t] != 0;
}
int dinic(int pos, int limit) {
	if (pos == t) return limit;
	int used = 0, tmp;
	for (unsigned &i = curr[pos]; i < a[pos].size(); i++)
		if (a[pos][i].flow && d[pos] + 1 == d[a[pos][i].dest] && (tmp = dinic(a[pos][i].dest, min(limit - used, a[pos][i].flow)))) {
			a[pos][i].flow -= tmp;
			a[a[pos][i].dest][a[pos][i].pos].flow += tmp;
			used += tmp;
			if (used == limit) return used;
		}
	return used;
}
int point(int x, int y) {
	return (x - 1) * m + y;
}
void insert(int x, int y) {
	a[x].push_back((edge) {y, 1, a[y].size()});
	a[y].push_back((edge) {x, 0, a[x].size() - 1});
}
bool legal(int x, int y) {
	return x >= 1 && x <= n && y >= 1 && y <= m;
}
void work(int x, int y) {
	visited[x][y] = true;
	int tmp = point(x, y);
	if (mp[x][y] == mp[homex][homey]) {
		insert(s, tmp);
		if (legal(x, y - 1) && mp[x][y] != mp[x][y - 1]) {
			insert(tmp, point(x, y - 1));
			if (!visited[x][y - 1]) work(x, y - 1);
		}
		if (legal(x, y + 1) && mp[x][y] != mp[x][y + 1]) {
			insert(tmp, point(x, y + 1));
			if (!visited[x][y + 1]) work(x, y + 1);
		}
		if (legal(x - 1, y) && mp[x][y] != mp[x - 1][y]) {
			insert(tmp, point(x - 1, y));
			if (!visited[x - 1][y]) work(x - 1, y);
		}
		if (legal(x + 1, y) && mp[x][y] != mp[x + 1][y]) {
			insert(tmp, point(x + 1, y));
			if (!visited[x + 1][y]) work(x + 1, y);
		}
	} else {
		insert(tmp, t);
		if (legal(x, y - 1) && mp[x][y] != mp[x][y - 1])
			if (!visited[x][y - 1]) work(x, y - 1);
		if (legal(x, y + 1) && mp[x][y] != mp[x][y + 1])
			if (!visited[x][y + 1]) work(x, y + 1);
		if (legal(x - 1, y) && mp[x][y] != mp[x - 1][y])
			if (!visited[x - 1][y]) work(x - 1, y);
		if (legal(x + 1, y) && mp[x][y] != mp[x + 1][y])
			if (!visited[x + 1][y]) work(x + 1, y);
	}
}
bool func(char type) {
	mp[homex][homey] = type;
	s = 0, t = n * m + 1;
	memset(visited, false, sizeof(visited));
	for (int i = s; i <= t; i++)
		a[i].clear();
	work(homex, homey);
	int ans = 0;
	while (bfs()) {
		memset(curr, 0, sizeof(curr));
		ans += dinic(s, INF);
	}
	memset(visited, false, sizeof(visited));
	for (int i = s; i <= t; i++)
		a[i].clear();
	work(homex, homey);
	a[point(homex, homey)].clear();
	int tans = 0;
	while (bfs()) {
		memset(curr, 0, sizeof(curr));
		tans += dinic(s, INF);
	}
	return ans != tans;
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("\n");
		for (int j = 1; j <= m; j++) {
			scanf("%c", &mp[i][j]);
			if (mp[i][j] == '.') {
				homex = i;
				homey = j;
			}
		}
	}
	int q, cnt = 0;
	static int ans[MAXK];
	scanf("%d", &q);
	for (int i = 1; i <= q; i++) {
		int x, y;
		scanf("%d%d", &x, &y);
		bool flg = func('X');
		swap(mp[x][y], mp[homex][homey]);
		homex = x; homey = y;
		if (flg && func('O')) ans[++cnt] = i;
		scanf("%d%d", &x, &y);
		swap(mp[x][y], mp[homex][homey]);
		homex = x; homey = y;
	}
	printf("%d\n", cnt);
	for (int i = 1; i <= cnt; i++)
		printf("%d\n", ans[i]);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值