2437: [Noi2011]兔兔与蛋蛋 - BZOJ

时间:2023-07-01 22:54:54
2437: [Noi2011]兔兔与蛋蛋 - BZOJ

Description

2437: [Noi2011]兔兔与蛋蛋 - BZOJ

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

2437: [Noi2011]兔兔与蛋蛋 - BZOJ

神题,竟然是二分图匹配,看了题解才知道

因为走的路线黑白交替所以我们考虑二分图匹配,相邻的黑白连边(空格一开始视为黑色)

然后可以发现走的路线是一条交错轨,那么必胜的条件是起点一定在最大匹配中

如果在的话,那么我们每次都走匹配边,最后没有路的一定是后手(可以画图yy一下,交错轨走到最后一定是一条匹配边,要不然起点就不一定在最大匹配中了)

如果起点不一定在最大匹配中那么,起点连的点都一定在最大匹配中(在去掉起点之后)(可以用反证法)

 const
maxn=;
maxk=;
var
p,a:array[..maxn,..maxn]of longint;
first,last,next:array[..maxn*maxn*]of longint;
link:array[..maxn*maxn]of longint;
vis:array[..maxn*maxn]of boolean;
ans:array[..maxk]of longint;
n,m,k,tot,cnt,xi,yi:longint; procedure insert(x,y:longint);
begin
inc(tot);last[tot]:=y;next[tot]:=first[x];first[x]:=tot;
inc(tot);last[tot]:=x;next[tot]:=first[y];first[y]:=tot;
end; function find(x:longint):boolean;
var
i:longint;
begin
if x< then exit(false);
i:=first[x];
while i<> do
begin
if not vis[last[i]] then
begin
vis[last[i]]:=true;
if (link[last[i]]=) or (find(link[last[i]])) then
begin
link[x]:=last[i];
link[last[i]]:=x;
exit(true);
end;
end;
i:=next[i];
end;
exit(false);
end; procedure main;
var
i,j,v:longint;
c:char;
flag1,flag2:boolean;
begin
read(n,m);
for i:= to n do
for j:= to m do
begin
inc(cnt);p[i,j]:=cnt;
repeat
read(c);
until (c='X') or (c='O') or (c='.');
if c='.' then
begin
xi:=i;
yi:=j;
end;
if c<>'O' then a[i,j]:=;
if (i>) and (a[i,j]<>a[i-,j]) then insert(p[i,j],p[i-,j]);
if (j>) and (a[i,j]<>a[i,j-]) then insert(p[i,j],p[i,j-]);
end;
for i:= to n do
for j:= to m do
if a[i,j]= then
begin
fillchar(vis,sizeof(vis),false);
find(p[i,j]);
end;
read(k);cnt:=;
for i:= to k do
begin
v:=link[p[xi,yi]];link[v]:=;
link[p[xi,yi]]:=-;
fillchar(vis,sizeof(vis),false);
if v= then flag1:=false
else flag1:=not find(v);
read(xi,yi);
v:=link[p[xi,yi]];link[v]:=;
link[p[xi,yi]]:=-;
fillchar(vis,sizeof(vis),false);
if v= then flag2:=false
else flag2:=not find(v);
read(xi,yi);
if flag1 and flag2 then
begin
inc(cnt);ans[cnt]:=i;
end;
end;
writeln(cnt);
for i:= to cnt do writeln(ans[i]);
end; begin
main;
end.