【BZOJ1443】【JSOI2009】游戏Game

【题目链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	105
#define MAXP	10005
#define INF	1e9
struct edge {int dest, flow; unsigned pos; };
vector <edge> a[MAXP];
unsigned curr[MAXP], d[MAXP], p[MAXP];
int n, m, s, t;
char mp[MAXN][MAXN];
bool bfs() {
	static int q[MAXP];
	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;
}
void pfs() {
	static int q[MAXP];
	int l = 0, r = 0;
	memset(p, 0, sizeof(p));
	q[0] = t; p[t] = 1;
	while (l <= r) {
		int tmp = q[l];
		for (unsigned i = 0; i < a[tmp].size(); i++)
			if (a[tmp][i].flow == 0 && p[a[tmp][i].dest] == 0) {
				q[++r] = a[tmp][i].dest;
				p[q[r]] = p[tmp] + 1;
			}
		l++;
	}
}
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;
}
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});
}
int point(int x, int y) {
	return (x - 1) * m + y;
}
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]);
	}
	s = 0; t = n * m + 1;
	int goal = 0;
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++) {
		if (mp[i][j] == '#') continue;
		goal++;
		int tmp = point(i, j);
		if ((i & 1) ^ (j & 1)) {
			insert(s, tmp);
			if (mp[i][j - 1] == '.') insert(tmp, point(i, j - 1));
			if (mp[i][j + 1] == '.') insert(tmp, point(i, j + 1));
			if (mp[i - 1][j] == '.') insert(tmp, point(i - 1, j));
			if (mp[i + 1][j] == '.') insert(tmp, point(i + 1, j));
		} else insert(tmp, t);
	}
	int flow = 0;
	while (bfs()) {
		memset(curr, 0, sizeof(curr));
		flow += dinic(s, INF);
	}
	if (flow * 2 == goal) {
		printf("LOSE\n");
		return 0;
	}
	printf("WIN\n");
	bfs();
	pfs();
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++) {
		if (mp[i][j] == '#') continue;
		if ((i & 1) ^ (j & 1)) {
			if (d[point(i, j)]) printf("%d %d\n", i, j);
		} else {
			if (p[point(i, j)]) printf("%d %d\n", i, j);
		}
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值