【bzoj1443】【JSOI2009】【游戏game】【二分图博弈】

来源:互联网 发布:winbox mac 登录 ros 编辑:程序博客网 时间:2024/05/09 17:54

Description

Input

输入数据首先输入两个整数N,M,表示了迷宫的边长。 接下来N行,每行M个字符,描述了迷宫。

Output

若小AA能够赢得游戏,则输出一行"WIN",然后输出所有可以赢得游戏的起始位置,按行优先顺序输出 每行一个,否则输出一行"LOSE"(不包含引号)。

Sample Input

3 3
.##
...
#.#

Sample Output

WIN
2 3
3 2

HINT

对于100%的数据,有1≤n,m≤100。 对于30%的数据,有1≤n,m≤5。

题解:

         可以看出来是二分图博弈的模型。

         对图黑白染色之后判断先手是否必胜跑一遍匈牙利算法看一下是否存在完备匹配即可。

         如果存在一定是先手必败。

         对于第二问,我们可以记录一下左边没有匹配的点。

         从这些点开始dfs,从左到右走非匹配边,从右向左走匹配边。

         这样dfs到的左边的点就是答案。

         然后把二分图左右两边倒过来再做一遍即可。

代码:

#include<iostream>#include<cstdio>#include<cstring>#define N 510using namespace std;int t1,t2,pos[N][N],x[4]={1,0,-1,0},y[4]={0,1,0,-1},bl[N*N];int n,m,cnt,point[N*N],next[N*N],num,to[N*N];bool f[N*N],vis[2][N*N],p[N*N];char s[N][N];void add(int x,int y){next[++cnt]=point[x];point[x]=cnt;to[cnt]=y;}bool find(int x){   for (int i=point[x];i;i=next[i])    if (!f[to[i]]){      f[to[i]]=1;      if (!bl[to[i]]||find(bl[to[i]])){bl[to[i]]=x;return true;}}   return false;}void dfs(int x,bool vis[]){  vis[x]=1;  for (int i=point[x];i;i=next[i])    if (!vis[bl[to[i]]])dfs(bl[to[i]],vis);}int main(){  scanf("%d%d",&n,&m);  for (int i=1;i<=n;i++) scanf("%s",s[i]+1);  for (int i=1;i<=n;i++)   for (int j=1;j<=m;j++)     if (s[i][j]=='.') pos[i][j]=++(i+j&1?t1:t2);  for(int i=1;i<=n;i++)   for (int j=1;j<=m;j++)    if (s[i][j]=='.'&&(i+j&1))     for (int k=0;k<4;k++){      int px=i+x[k],py=j+y[k];  if (px<=0||py<=0||px>n||py>m||s[px][py]=='#') continue;  add(pos[i][j],pos[px][py]);        }  for (int i=1;i<=t1;i++){    memset(f,0,sizeof(f));    if (find(i)) num++;else p[i]=1;  }  if (num==t1&&num==t2){printf("LOSE\n");return 0;}  for (int i=1;i<=t1;i++) if (p[i]) dfs(i,vis[1]);  memset(point,0,sizeof(point));  memset(p,0,sizeof(p));  memset(bl,0,sizeof(bl));  for (int i=1;i<=n;i++)   for (int j=1;j<=m;j++)    if (s[i][j]=='.'&&((i+j)%2==0)){      for (int k=0;k<4;k++){        int px=i+x[k],py=j+y[k];        if (px<=0||py<=0||px>n||py>m||s[px][py]=='#') continue;    add(pos[i][j],pos[px][py]);          }    }  for (int i=1;i<=t2;i++){    memset(f,0,sizeof(f));    if (!find(i)) p[i]=1;  }  for (int i=1;i<=t2;i++) if (p[i]) dfs(i,vis[0]);  printf("WIN\n");   for (int i=1;i<=n;i++)   for (int j=1;j<=m;j++){    if ((i+j&1)&&(vis[1][pos[i][j]]))printf("%d %d\n",i,j);    if (((i+j)%2==0)&&(vis[0][pos[i][j]])) printf("%d %d\n",i,j);   }}


0 0
原创粉丝点击