LOJ#6033. 「雅礼集训 2017 Day2」棋盘游戏 题解

题目链接

把每个非 '#' 的格子当成点,共用边的格子所代表的点之间连一条边,不难发现这是个二分图。

不难发现这个二分图上的博弈,先手必胜当且仅当起始点一定会被包含在最大匹配中,否则后手只要一直走匹配边就赢了。

那么我们判断每个点是否可以成为这样的起始点即可。

求最大匹配的部分可以使用匈牙利算法也可以直接网络流,复杂度为 \(\Theta(n^2m^2)\)\(\Theta((nm)^{1.5})\)

code :

#include <bits/stdc++.h>
using namespace std;
template <typename T> void read(T &x){
	static char ch; x = 0,ch = getchar();
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
}
inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }
inline int Get(){
	static char ch; ch = getchar();
	while (ch != '.' && ch != '#') ch = getchar();
	return ch == '.' ? 1 : 0;
}
const int N = 105,V = N * N;
int n,m,mp[N][N],id[N][N],cntv; 
int G[V][4],deg[V];
inline void add(int x,int y){ G[x][deg[x]++] = y; G[y][deg[y]++] = x; }
int match[V]; bool vis[V];
inline bool dfs(int x){
	if (vis[x]) return 0; vis[x] = 1;
	for (int y,i = 0; i < deg[x]; ++i)
		if (!match[y=G[x][i]] || dfs(match[y])){ match[y] = x,match[x] = y; return 1; }
	return 0;
}
inline void dfs_ans(int x){
	if (vis[x]) return; vis[x] = 1;
	for (int y,i = 0; i < deg[x]; ++i) if (match[y=G[x][i]]) dfs_ans(match[y]);
}
int main(){
	int i,j;
	read(n),read(m);
	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mp[i][j] = Get()) id[i][j] = ++cntv;
	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mp[i][j] && ((i+j)&1)){
		if (id[i-1][j]) add(id[i][j],id[i-1][j]);
		if (id[i+1][j]) add(id[i][j],id[i+1][j]);
		if (id[i][j-1]) add(id[i][j],id[i][j-1]);
		if (id[i][j+1]) add(id[i][j],id[i][j+1]);
	}
	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mp[i][j] && ((i+j)&1))
		memset(vis,0,cntv+1),dfs(id[i][j]);
	memset(vis,0,cntv+1);
	for (i = 1; i <= cntv; ++i) if (!match[i]) dfs_ans(i);
	int ans = 0;
	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (id[i][j] && vis[id[i][j]]) ++ans;
	write(ans),putchar('\n');
	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (id[i][j] && vis[id[i][j]]) write(i),putchar(' '),write(j),putchar('\n');
	return 0;
}
posted @ 2020-09-30 20:55  srf  阅读(337)  评论(0编辑  收藏  举报