Description

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对应图三中的游戏过程

Sol

最近补了几发博弈论,但都是和sg函数有关的博弈,看到这题就懵了。

后来才知道这个叫二分图博弈......

具体地,这个操作相当于在移动这个空格,我们把空格变成黑色,那么就是按照黑白黑白黑白的顺序走,这好像有点二分图的感觉...

然后我们把合法的点拉出来建四联通的二分图(到起点的曼哈顿距离和它的颜色正好匹配),之后这个博弈其实就是在二分图上跑增广路,而且经过的边不能再次经过,这样的话我们发现,一个点是必胜态当且仅当这个点一定是一个最大匹配包含的点,因为匹配边和连接匹配的边总个数是个奇数。。。只要一直顺着匹配连边走就能赢。。。(对手走的是连接两对匹配的边)否则的话一定是必败态(因为走一步一定走到了一个最大匹配上,假设走不到说明还有新的匹配,与最大匹配矛盾,不成立)。

至于判断一个点是不是最大匹配的必需点,我们把它删掉,从它的原匹配点如果能找到最短路,说明它不是必需点。判断有没有做错是需要判断两个连续的状态是不是都是必胜态。。。

然后好像就完了......

Code

#include <bits/stdc++.h>
using namespace std;
char s[45][45];vector<int>e[2500];
int n,m,q,tot,Index,ans,a[45][45],sx,sy,u,v,vis[2500],match[2500],del[2500],win[2500];
bool dfs(int x)
{
for(int i=0;i<e[x].size();i++)
{
if(del[e[x][i]]||vis[e[x][i]]==Index) continue;
vis[e[x][i]]=Index;
if(!match[e[x][i]]||dfs(match[e[x][i]])){match[e[x][i]]=x,match[x]=e[x][i];return 1;}
}
return 0;
}
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]=='.'){sx=i,sy=j,s[i][j]='X';break;}
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
if((s[i][j]=='O'&&(abs(i-sx)+abs(j-sy))%2==1)||(s[i][j]=='X'&&(abs(i-sx)+abs(j-sy))%2==0)) a[i][j]=++tot;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(a[i][j])
{
if(a[i-1][j]) e[a[i][j]].push_back(a[i-1][j]);if(a[i+1][j]) e[a[i][j]].push_back(a[i+1][j]);
if(a[i][j-1]) e[a[i][j]].push_back(a[i][j-1]);if(a[i][j+1]) e[a[i][j]].push_back(a[i][j+1]);
}
for(int i=1;i<=tot;i++) if(!match[i]) Index++,dfs(i);
scanf("%d",&q);q<<=1;
for(int i=1;i<=q;i++)
{
u=a[sx][sy];
if(match[u]) v=match[u],match[u]=match[v]=0,del[u]=1,Index++,win[i]=!dfs(v);
else del[u]=1,win[i]=0;
scanf("%d%d",&sx,&sy);
}
for(int i=1;i<=q;i++,i++) if(win[i]&&win[i+1]) ans++;
printf("%d\n",ans);
for(int i=1;i<=q;i++,i++) if(win[i]&&win[i+1]) printf("%d\n",(i+1)>>1);
}

【bzoj2437】[Noi2011]兔兔与蛋蛋 二分图最大匹配+博弈论的更多相关文章

  1. 【BZOJ2437】【NOI2011】兔兔与蛋蛋(博弈论,二分图匹配)

    [BZOJ2437][NOI2011]兔兔与蛋蛋(博弈论,二分图匹配) 题面 BZOJ 题解 考虑一下暴力吧. 对于每个状态,无非就是要考虑它是否是必胜状态 这个直接用\(dfs\)爆搜即可. 这样子 ...

  2. 【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)

    未经博主同意不得转载 2437: [Noi2011]兔兔与蛋蛋 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 693  Solved: 442 Des ...

  3. bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势

    noi2011 兔兔与蛋蛋 题目大意 直接看原题吧 就是\(n*m\)的格子上有一些白棋和一些黑棋和唯一一个空格 兔兔先手,蛋蛋后手 兔兔要把与空格相邻的其中一个白棋移到空格里 蛋蛋要把与空格相邻的其 ...

  4. BZOJ.2437.[NOI2011]兔兔与蛋蛋游戏(二分图博弈 匈牙利)

    题目链接 首先空格的移动等价于棋子在黑白格交替移动(设起点移向白格就是黑色),且不会走到到起点距离为奇数的黑格.到起点距离为偶数的白格(删掉就行了),且不会重复走一个格子. (然后策略就同上题了,只不 ...

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

    Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...

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

    Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...

  7. NOI2011 兔兔与蛋蛋游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=2437 这道题真是极好的. 75分做法: 搜索. 出题人真的挺良心的,前15个数据点的范围都很小,可以 ...

  8. 【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)

    [BZOJ2432][NOI2011]兔农(数论,矩阵快速幂) 题面 BZOJ 题解 这题\(75\)分就是送的,我什么都不想写. 先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后 把它减 ...

  9. POJ 2226二分图最大匹配

    匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...

随机推荐

  1. windows右键打开方式里面添加新的应用程序

    1.打开注册表编辑器.打开运行窗口,快捷键,开始+R.输入“regedit”,回车确定. 2.进入注册表编辑器的HKEY_CLASSES_ROOT文件夹下的*子文件夹下的shell文件夹. 3.右键s ...

  2. C# winform开发

    一处消息死锁分析 最近维护一个工控机上运行的winform程序,我的前任在一个弹出窗口(窗口B)里面调用了ShowDialog方法弹出对话框(窗口C),导致了一个问题是有时关闭窗口C时windows假 ...

  3. stm32中断 抢占优先级 和 响应优先级 有什么区别

    与51不同,stm32的中断分类更灵活.51只是按先后顺序大小排列互相打断. stm32中多了响应优先级这一概念. stm32的中断分为 1.抢占(占先)优先级. 2.响应优先级. 1.抢占优先级.抢 ...

  4. printf("%f\n", 3);输出结果为什么是0.000000(转载)

    printf不会关心你输入的参数的类型,你输入的实际是 printf("%f",3),但是这个整型3不会被隐式类型转换为浮点型,而是被直接按内存内容当作浮点型 也就是说,内部使用等 ...

  5. Python 小练习一

    1.如果同一个ip地址60s之内访问超过200次,那么就把ip加入黑名单 需求分析: 1.60s读一次文件 2.分割,取第一个元素,ip地址 3.把所有ip加入到一个list里面,如果ip次数超过20 ...

  6. 【280】◀▶ ArcPy 常用工具说明

    目录: 一.相关技巧 二.工具说明 一.相关技巧 技巧1:将工具从工具箱拖拽到 Python 窗体中自动会生成相应的函数,于是可以快速定位函数名称! 技巧2:将通过工具箱实现的操作结果拖拽到 Pyth ...

  7. imp导入数据的时候报错:ORA-01658: 无法为表空间 MAXDATA 中的段创建 INITIAL 区

    在oracle里创建表,报出错: ORA-01658: 无法为表空间space中的段创建 INITIAL 区: 或者: ORA-01658: unable to create INITIAL exte ...

  8. codeforce467DIV2——D. Sleepy Game

    分析 这个题乍一看有点像之前在CF上做过的一道DP,也是两个人下棋,但是写着写着觉得不对···这个题是的最优策略只是player 1 如果有环则是draw,可以DFS的时候顺便判环(拓扑排序的方法), ...

  9. CentOS双网卡双IP设置

    CentOS双网卡双IP设置 系统环境:CentOS Linux 网络环境: 两个IP地址,192.168.0.10和10.10.30.2,掩码是255.255.255.0,这两个子网的网关地址分别是 ...

  10. 10.IN 操作符

    IN 操作符 IN 操作符允许我们在 WHERE 子句中规定多个值. SQL IN 语法 SELECT column_name(s) FROM table_name WHERE column_name ...