题目链接
题解
既然是网格图,便可以二分染色
二分染色后发现,游戏路径是黑白交错的
让人想到匹配时的增广路
后手要赢【指移动的后手】,必须在一个与起点同色的地方终止
容易想到完全匹配的图先手是必胜的,因为完全匹配的图要么走到对面终止,要么从对面找一条非匹配边走回来,而由于是完全匹配,总能继续走下去,所以先手总能走到一个不同色点
于是乎对于一个匹配完的二分图,我们从一个未匹配的点出发,此时先手只能走未匹配边,而由于已经是匹配完毕,所以走到的点一定是已匹配的点,此时我们可以继续走到该点的匹配点,先手要么无法操作,要么继续走一条未匹配边
换言之,我们走的总是交错边,而交错边上的匹配情况是可以互换的,所以从一个未匹配的点出发能走到的同侧的点都是后手必胜的
也不知道为什么(O(n^3))怎么能跑(10^4)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 10005,maxm = 1000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int N,M,n,cnt;
int h[maxn],ne;
struct EDGE{int to,nxt;}ed[maxm];
inline void build(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
char s[105][105];
int id[105][105],c[maxn],x[maxn],y[maxn];
void dfs1(int u){
Redge(u) if (c[to = ed[k].to] == -1)
c[to] = c[u] ^ 1,dfs1(to);
}
int lk[maxn],vis[maxn],ok[maxn];
bool find(int u){
Redge(u) if (!vis[to = ed[k].to]){
vis[to] = true;
if (!lk[to] || find(lk[to])){
lk[to] = u;
return true;
}
}
return false;
}
void dfs(int u){
if (ok[u]) return;
ok[u] = true;
Redge(u) if (lk[to = ed[k].to]) dfs(lk[to]);
}
inline bool cmp(const int& a,const int& b){
return x[a] == x[b] ? y[a] < y[b] : x[a] < x[b];
}
int main(){
N = read(); M = read();
REP(i,N){
scanf("%s",s[i] + 1);
REP(j,M) if (s[i][j] == '.') id[i][j] = ++n,x[n] = i,y[n] = j;
}
REP(i,N) REP(j,M){
if (!id[i][j]) continue;
if (id[i + 1][j]) build(id[i][j],id[i + 1][j]);
if (id[i][j + 1]) build(id[i][j],id[i][j + 1]);
}
REP(i,n) c[i] = -1;
REP(i,n) if (c[i] == -1) c[i] = 0,dfs1(i);
REP(i,n) if (c[i]) cls(vis),cnt += find(i);
if (cnt * 2 == n){puts("LOSE"); return 0;}
REP(i,n) if (!c[i]) lk[lk[i]] = i;
REP(i,n) if (!lk[i]) dfs(i);
puts("WIN");
REP(i,n) if (ok[i]) printf("%d %d
",x[i],y[i]);
return 0;
}