【bzoj2437】[Noi2011]兔兔与蛋蛋 二分图最大匹配+博弈论
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]兔兔与蛋蛋 二分图最大匹配+博弈论的更多相关文章
- 【BZOJ2437】【NOI2011】兔兔与蛋蛋(博弈论,二分图匹配)
[BZOJ2437][NOI2011]兔兔与蛋蛋(博弈论,二分图匹配) 题面 BZOJ 题解 考虑一下暴力吧. 对于每个状态,无非就是要考虑它是否是必胜状态 这个直接用\(dfs\)爆搜即可. 这样子 ...
- 【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)
未经博主同意不得转载 2437: [Noi2011]兔兔与蛋蛋 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 693 Solved: 442 Des ...
- bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势
noi2011 兔兔与蛋蛋 题目大意 直接看原题吧 就是\(n*m\)的格子上有一些白棋和一些黑棋和唯一一个空格 兔兔先手,蛋蛋后手 兔兔要把与空格相邻的其中一个白棋移到空格里 蛋蛋要把与空格相邻的其 ...
- BZOJ.2437.[NOI2011]兔兔与蛋蛋游戏(二分图博弈 匈牙利)
题目链接 首先空格的移动等价于棋子在黑白格交替移动(设起点移向白格就是黑色),且不会走到到起点距离为奇数的黑格.到起点距离为偶数的白格(删掉就行了),且不会重复走一个格子. (然后策略就同上题了,只不 ...
- 2437: [Noi2011]兔兔与蛋蛋 - BZOJ
Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...
- 博弈论(二分图匹配):NOI 2011 兔兔与蛋蛋游戏
Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...
- NOI2011 兔兔与蛋蛋游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=2437 这道题真是极好的. 75分做法: 搜索. 出题人真的挺良心的,前15个数据点的范围都很小,可以 ...
- 【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)
[BZOJ2432][NOI2011]兔农(数论,矩阵快速幂) 题面 BZOJ 题解 这题\(75\)分就是送的,我什么都不想写. 先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后 把它减 ...
- POJ 2226二分图最大匹配
匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...
随机推荐
- openstack resize 更新显卡驱动程序解决问题
- [C#] 等待启动的进程执行完毕
有能有时候我们启动了一个进程,必须等到此进程执行完毕,或是,一段时间, 关闭进程后再继续往下走. Example sample1 等待应用程序执行完毕 //等待应用程序执行完毕 private voi ...
- leetcode690
class Solution { public: int getImportance(vector<Employee*> employees, int id) { ; map<int ...
- C++深度解析教程学习笔记(6)对象的构造和销毁
1. 对象的初始化 (1)从程序设计的角度看,对象只是变量,因此: ①在栈上创建对象时,成员变量初始化为随机值 ②在堆上创建对象时,成员变量初始化为随机值 ③在静态存储区创建对象时,成员变量初始化为 ...
- Stall Reservations(贪心+优先队列)
Description Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will onl ...
- C#向pdf 添加水印
调用直接这样用: //PDFHelper.AddImageWatermarkPDF(path, "D://my.pdf", Server.MapPath("/HtmlTo ...
- Tornado之抽屉实战(3)--注册
知识点应用:标签绑定事件,jQuery获取用户值-->AJAX发送数据-->后台路由系统-->业务逻辑处理-->ORM数据操作-->write返回-->AJAX回调 ...
- libevent源码深度剖析六
libevent源码深度剖析六 ——初见事件处理框架 张亮 前面已经对libevent的事件处理框架和event结构体做了描述,现在是时候剖析libevent对事件的详细处理流程了,本节将分析 lib ...
- 在ubuntu12.04上安装6款顶级漂亮的BURG主题
BURG 基本上是一个基于GRUB的Linux引导装载程序.BURG格有一个高度可配置的菜单系统,可选择文本和图形模式.简而言之,BURG可广泛定制,有良好免费的BURG主题.选择自己最喜欢的,下面我 ...
- 堡垒机(paramiko)
实现思路 堡垒机执行流程: 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码) 用户登陆堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表 用户选择服务器,并自动登陆 执行 ...