Description

博弈论(二分图匹配):NOI 2011 兔兔与蛋蛋游戏-LMLPHP

Input

输入的第一行包含两个正整数 n、m。
接下来 n行描述初始棋盘。其中第i 行包含 m个字符,每个字符都是大写英文字母"X"、大写英文字母"O"或点号"."之一,分别表示对应的棋盘格中有黑色棋子、有白色棋子和没有棋子。其中点号"."恰好出现一次。
接下来一行包含一个整数 k(1≤k≤1000) ,表示兔兔和蛋蛋各进行了k次操作。
接下来 2k行描述一局游戏的过程。其中第 2i – 1行是兔兔的第 i 次操作(编号为i的操作) ,第2i行是蛋蛋的第i次操作。每个操作使用两个整数x,y来描述,表示将第x行第y列中的棋子移进空格中。
输入保证整个棋盘中只有一个格子没有棋子, 游戏过程中兔兔和蛋蛋的每个操作都是合法的,且最后蛋蛋获胜。

Output

输出文件的第一行包含一个整数r,表示兔兔犯错误的总次数。
接下来r 行按递增的顺序给出兔兔“犯错误”的操作编号。其中第 i 行包含一个整数ai表示兔兔第i 个犯错误的操作是他在游戏中的第 ai次操作。
1 ≤n≤ 40, 1 ≤m≤ 40

Sample Input

样例一:
1 6
XO.OXO
1
1 2
1 1
样例二:
3 3
XOX
O.O
XOX
4
2 3
1 3
1 2
1 1
2 1
3 1
3 2
3 3
样例三:
4 4
OOXX
OXXO
OO.O
XXXO
2
3 2
2 2
1 2
1 3

Sample Output

样例一:
1
1
样例二:
0
样例三:
2
1
2

样例1对应图一中的游戏过程
样例2对应图三中的游戏过程

HINT

博弈论(二分图匹配):NOI 2011 兔兔与蛋蛋游戏-LMLPHP

  这道题很好,思维巧妙又不难打。题解直接引用maijing的:

  然后代码极简单。

 #include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=;
const int M=;
int cnt,cntX,cntO;
int fir[N],to[M],nxt[M];
int match[N],vis[N],ban[N],id[][],ans[];
char map[][];
int n,m,px,py;
int tx[]={,,,-};
int ty[]={,,-,};
void addedge(int a,int b){
nxt[++cnt]=fir[a];to[fir[a]=cnt]=b;
} bool DFS(int x){
for(int i=fir[x];i;i=nxt[i])
if(!vis[to[i]]&&!ban[to[i]]){vis[to[i]]=;
if(!match[to[i]]||DFS(match[to[i]]))
{match[match[to[i]]=x]=to[i];return true;}
}
return false;
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%s",map[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
if(map[i][j]=='.')
map[i][j]='X',px=i,py=j;
if(map[i][j]=='O')
id[i][j]=++cntO;
else if(map[i][j]=='X')
id[i][j]=++cntX;
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(map[i][j]=='O')
id[i][j]+=cntX; for(int i=;i<=n;i++)
for(int j=;j<=m;j++)if(id[i][j]){
for(int k=;k<;k++){
int gx=tx[k]+i,gy=ty[k]+j;
if(map[gx][gy]!=map[i][j])
addedge(id[i][j],id[gx][gy]);
}
}
for(int i=;i<=cntX;i++)if(!match[i])
{memset(vis,,sizeof(vis));DFS(i);} int k;scanf("%d",&k);
for(int i=;i<=*k;i++){
int x;ban[x=id[px][py]]=;
if(match[x]){int y=match[x];
memset(vis,,sizeof(vis));
match[x]=match[y]=;
ans[i]=DFS(y)^;
}
scanf("%d%d",&px,&py);
}
int ret=;
for(int i=;i<=k;i++)
ret+=ans[i*]&ans[i*-];
printf("%d\n",ret);
for(int i=;i<=k;i++)
if(ans[i*]&ans[i*-])
printf("%d\n",i);
return ;
}
04-17 12:05