题目描述
小AA和小YY得到了《喜羊羊和灰太狼》的电影票,都很想去观看,但是电影票只有一张,于是他们用智力游戏决定胜负,赢得游戏的人可以获得电影票。在N*M的迷宫中有一个棋子,小AA首先任意选择棋子放置的位置。然后,小YY和小AA轮流将棋子移动到相邻的格子里。游戏的规则规定,在一次游戏中,同一个格子不能进入两次,且不能将棋子移动到某些格子中去。当玩家无法继续移动棋子时,游戏结束,最后一个移动棋子的玩家赢得了游戏。例如下图所示的迷宫,迷宫中”.”表示棋子可以经过的格子,而”#”表示棋子不可以经过的格子:
.##
...
#.#
若小AA将棋子放置在(1,1),则小 AA 则无论如何都无法赢得游戏。
而若小AA将棋子放置在(3,2)或(2,3),则小AA能够赢得游戏。例如,小AA将棋子放置在(3,2),小YY只能将它移动到(2,2),此时小AA再将棋子移动到(2,3),就赢得了游戏。
小AA和小YY都是绝顶聪明的小朋友,且从不失误。小AA到底能不能赢得这场游戏,从而得到珍贵的电影票呢?
输入输出格式
输入格式:
输入数据首先输入两个整数 N,M,表示了迷宫的边长。接下来 N 行,每行 M 个字符,描述了迷宫。
输出格式:
若小 AA 能够赢得游戏,则输出一行”WIN”,然后输出所有可以赢得游戏的起始位置,按行优先顺序输出,每行一个。否则输出一行”LOSE”(不包含引号)。
输入输出样例
输入样例#1:
3 3
.##
…
#.#
输出样例#1:
WIN
2 3
3 2
说明
对30%的数据,有1<=n,m<=5,对100%的数据,有1<=n,m<=100.
分析
这道题要是没有不可到的地方,就和这道题一样了,然而,它有阻挡,所以自然想到二分图匹配,对于先手而言,若二分图不存在完美匹配,则放在非匹配点一定是最优的。因为后手的第一步必定走到一个匹配点,先手只需要保证一直沿着匹配边走即可,因为不可能存在非匹配边、匹配边交叉出现的增广路,即先手总是能比后手多走一步(根据最大匹配的定义),若二分图存在完美匹配,那么先手无论如何放置都会输,具体同理,那么先判断是否是完美匹配,若是这道题也就完了,不是的话找到非匹配点就行了,时间:4500ms。
上代码
#include<bits/stdc++.h>
using namespace std;
int next[200001],head[200001],now=0,point[200001],match[200001],x[200001],y[200001],mat[200001],dx[5]={0,0,0,1,-1},dy[5]={0,1,-1,0,0};
bool visit[200001],mark[200001];
char ch[200][200];
void add(int x,int y){ next[++now]=head[x],head[x]=now,point[now]=y;}
bool dfs(int k){
for(int i=head[k],u;i;i=next[i])
if(!visit[u=point[i]]){
visit[u]=1;
if(dfs(match[u])||match[u]==-1){
match[u]=k;
mat[k]=u;
return true;
}
}
return false;
}
int main(){
int n,m,u=0,v=0,flag=0,fi=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",ch[i]+1);
for(int i=1;i<=n;i++){
fi^=1;
for(int j=fi+1;j<=m;j+=2) if(ch[i][j]=='.'){
x[++u]=i*m+j;
for(int k=1;k<=4;k++){
int xx=i+dx[k],yy=j+dy[k];
if(ch[xx][yy]=='.') add(i*m+j,xx*m+yy),add(xx*m+yy,i*m+j);
}
}
}
fi=1;
for(int i=1;i<=n;i++){
fi^=1;
for(int j=fi+1;j<=m;j+=2) if(ch[i][j]=='.') y[++v]=i*m+j;
}
memset(match,-1,sizeof(match));
for(int i=1;i<=u;i++){
memset(visit,0,sizeof(visit));
if(!dfs(x[i])) flag=1,mark[x[i]]=1;
}
for(int i=1;i<=v;i++){
if(match[y[i]]==-1) mark[y[i]]=1,flag=1;
else{
memset(visit,0,sizeof(visit));
visit[y[i]]=1;
if(dfs(match[y[i]])) match[y[i]]=-1,mark[y[i]]=1,flag=1;
}
}
for(int i=1;i<=v;i++){
memset(visit,0,sizeof(visit));
if(!dfs(y[i])) flag=1,mark[y[i]]=1;
}
for(int i=1;i<=u;i++){
if(match[x[i]]==-1) mark[x[i]]=1,flag=1;
else{
memset(visit,0,sizeof(visit));
visit[x[i]]=1;
if(dfs(match[x[i]])) match[x[i]]=-1,mark[x[i]]=1,flag=1;
}
}
if(!flag){
printf("LOSE\n");
return 0;
}
printf("WIN\n");
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mark[i*m+j]) printf("%d %d\n",i,j);
return 0;
}