bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势
noi2011 兔兔与蛋蛋
题目大意
直接看原题吧
就是\(n*m\)的格子上有一些白棋和一些黑棋和唯一一个空格
兔兔先手,蛋蛋后手
兔兔要把与空格相邻的其中一个白棋移到空格里
蛋蛋要把与空格相邻的其中一个黑棋移到空格里
谁不能移动谁输
分析
这篇博客挺好的
我们可以将题意转化成兔兔将空格移到白棋那里
蛋蛋将空格移动到黑棋那里
转化成图黑白染色,变成二分图
我们设空格染成黑色
那空格移动的轨迹一定是:
黑\(~\)-白-黑-白-黑
对应的是:
空格-白棋-黑棋-白棋-黑棋
所以染成白色且为白棋\(~\)或\(~\)染成黑色且为黑棋
的才是合法点(其他点不可能移动的)
将相邻合法点连边
同时把空格当成黑棋看
又根据奇偶性,从空格从一个点出发不可能绕回那个点
博弈
假如我们现在求出了一个最大匹配
那么如果一个点一定在最大匹配中,那么他有必胜策略
否则没有
证明:
已匹配的边记为\(A\)
未匹配的边记为\(B\)
那么从一个点出发走到无路可走\(~~\)且\(~~\)有A尽量走A有以下几种情况:(图自行脑补)
根据匹配,不可能出现\(AA\)
思考一下,不可能出现\(BB\)(因为前一个\(B\)没有匹配边\(A\)了,后一个\(B\)无路可走了)
还有就是从一个点出发有\(B\)则那个点出发还一定有个\(A\)
1.\(ABAB\)
这种情况\(AB\)可以互换,最大匹配不变
出发点不一定在最大匹配中,先手走\(A\)会让对方有必胜策略
2.\(BABA\)
同上
出发点不一定在最大匹配中,先手走\(B\)会让对方有必胜策略
3.\(BABAB\)
因为从一个点出发有\(B\)则那个点出发还一定有个\(A\)
交换\(AB\)最大匹配不变,且出发点依然在最大匹配中
出发点一定在最大匹配中,先手走\(B\)或\(A\)都能赢
4.\(ABABA\)
这种情况出发点一定在最大匹配中,先手走\(A\)就赢了
做法
证明完了
现在如何判断一个点是否一定在最大匹配中呢?
首先如果本来就不在最大匹配直接就不行了
否则删掉这个点,并断掉这个点的匹配边,从它匹配点增广
匹配点能增广它就不一定在最大匹配了
做法
于是我们动态ban点
每读入一个操作就ban掉一个点就好了
姿势
匈牙利vis数组可以用时间戳
标号都不一样的话可以两边一起匹配
bool xyl(int x){
int p,y;
for(p=g[x];p;p=e[p].nxt)
if(vis[y=e[p].y]!=T&&!del[y]){
vis[y]=T;
if(lnk[y]==-1||xyl(lnk[y])){
lnk[y]=x;//
lnk[x]=y;//
return 1;
}
}
return 0;
}
int main(){
for(i=1;i<=cnt;i++)
if(lnk[i]==-1){
T++;
xyl(i);
}
}
solution
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
const int M=1603;
const int N=43;
inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
int n,m,nm,K,T;
int g[M],te;
struct edge{int y,nxt;}e[M<<3];
char s[N][N];
int num[N][N],cnt,ck;
bool win[2007];
int del[M];
int lnk[M];
int vis[M];
void addedge(int x,int y){
e[++te].y=y;e[te].nxt=g[x];g[x]=te;
}
bool xyl(int x){
int p,y;
for(p=g[x];p;p=e[p].nxt)
if(vis[y=e[p].y]!=T&&!del[y]){
vis[y]=T;
if(lnk[y]==-1||xyl(lnk[y])){
lnk[y]=x;
lnk[x]=y;
return 1;
}
}
return 0;
}
int main(){
int i,j,x,y,nw;
n=rd(),m=rd();
for(i=1;i<=n;i++) scanf("%s",s[i]+1);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(s[i][j]=='.'){
s[i][j]='X';//要使它有连边
x=i; y=j;//x,y存的是空格位置
ck=(i+j)%2;
break;
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++){
if(s[i][j]=='X'&&(i+j)%2==ck) num[i][j]=++cnt;
if(s[i][j]=='O'&&(i+j)%2!=ck) num[i][j]=++cnt;
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(num[i][j]){
if(i>1&&num[i-1][j]) addedge(num[i][j],num[i-1][j]);
if(i<n&&num[i+1][j]) addedge(num[i][j],num[i+1][j]);
if(j>1&&num[i][j-1]) addedge(num[i][j],num[i][j-1]);
if(j<m&&num[i][j+1]) addedge(num[i][j],num[i][j+1]);
}
memset(lnk,-1,sizeof(lnk));
for(i=1;i<=cnt;i++)
if(lnk[i]==-1){
T++;
xyl(i);
}
K=rd();
for(i=1;i<=K*2;i++){
nw=num[x][y];
del[nw]=1;
if(lnk[nw]==-1) win[i]=0;
else{
int tp=lnk[nw];
lnk[nw]=lnk[tp]=-1;
T++;
win[i]= !xyl(tp);
}
x=rd(),y=rd();
}
int ans=0;
for(i=1;i<=K;i++)
if(win[i*2]&&win[i*2-1]) ans++;
printf("%d\n",ans);
for(i=1;i<=K;i++)
if(win[i*2]&&win[i*2-1]) printf("%d\n",i);
return 0;
}
bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势的更多相关文章
- bzoj 2437: [Noi2011]兔兔与蛋蛋
Description Solution 考虑犯错误的条件:之前是处于必胜状态,该操作之后就变成了必败状态. 我们可以把这个过程看成两人对网格图进行黑白染色,变成了一个二分图模型,即当前位置向相邻不同 ...
- bzoj 2437 [Noi2011]兔子和鸡蛋 [二分图匹配]
叙述性说明 这些日子.兔子和蛋像一个新的棋盘游戏. 这场比赛是在 n 行 m 在船上进行列. 前,棋盘上有一 个格子是空的,其他的格子中都放置了一枚棋子,棋子或者是黑色,或者是白色. 每一局游戏总是兔 ...
- BZOJ.2756.[SCOI2012]奇怪的游戏(二分 黑白染色 最大流ISAP)
题目链接 \(Description\) \(Solution\) 这种题当然要黑白染色.. 两种颜色的格子数可能相同,也可能差1.记\(n1/n2\)为黑/白格子数,\(s1/s2\)为黑/白格子权 ...
- BZOJ 2131 圈地计划(最小割+黑白染色)
类似于happiness的一道题,容易想到最小割的做法. 但是不同的是那一道题是相邻的如果相同则有收益,这题是相邻的不同才有收益. 转化到建图上面时,会发现,两个相邻的点连的边容量会是负数.. 有一种 ...
- bzoj 1997: [Hnoi2010]Planar【瞎搞+黑白染色】
脑补一下给出的图:一个环,然后有若干连接环点的边,我们就是要求这些边不重叠 考虑一下不重叠的情况,两个有交边一定要一个在环内一个在环外,所以把相交的边连边,然后跑黑白染色看是否能不矛盾即可(可能算个2 ...
- BZOJ.1443.[JSOI2009]游戏Game(二分图博弈 匈牙利)
题目链接 \(Description\) 一个\(N*M\)的有障碍的棋盘,先手放置棋子后,从后手开始轮流移动棋子,不能走重复的位置,不能移动的输.求在哪些位置放棋子是先手必胜的. \(Solutio ...
- BZOJ.2437.[NOI2011]兔兔与蛋蛋游戏(二分图博弈 匈牙利)
题目链接 首先空格的移动等价于棋子在黑白格交替移动(设起点移向白格就是黑色),且不会走到到起点距离为奇数的黑格.到起点距离为偶数的白格(删掉就行了),且不会重复走一个格子. (然后策略就同上题了,只不 ...
- 【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)
未经博主同意不得转载 2437: [Noi2011]兔兔与蛋蛋 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 693 Solved: 442 Des ...
- 2437: [Noi2011]兔兔与蛋蛋 - BZOJ
Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...
随机推荐
- Dapper学习总结
看了<Dapper从入门到精通>后的总结 (1)Dapper 是直接扩展 IDBConnection,而且是单独一个文件,可以直接嵌入到项目中使用. (2)通过手写sql语句,调用exec ...
- ssh整合思想初步 struts2与Spring的整合 struts2-spring-plugin-2.3.4.1.jar下载地址 自动加载Spring中的XML配置文件 Struts2下载地址
首先需要JAR包 Spring整合Structs2的JAR包 struts2-spring-plugin-2.3.4.1.jar 下载地址 链接: https://pan.baidu.com/s/1o ...
- skynet 学习笔记-sproto模块(2)
云风在skynet中继承了sproto的传输协议,对比protobuf的好处是,能明文看到传输内容,而且skynet不需要protobuf这么功能,所以云风也建议在lua层使用sproto来作为sky ...
- 浅谈JavaScript中的正则表达式(适用初学者观看)
浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...
- 探讨 JS 的面向对象中继承的那些事
最近学了 JS 的面向对象,这篇文章主要是探讨 JS 的面向对象中继承的那些事. JS中继承的特点: 1.子类继承父类: 2.子类可以用父类的方法和属性 3.子类的改变可以不影响父类 下面用一个例子来 ...
- Linux - NodeJS安装
1> 去NodeJS官网 https://nodejs.org/en/ 或 中文网 http://nodejs.cn/download/ 拷贝相应版本的安装文件,如下图: 2> 执行 wg ...
- ubuntu16.04安装 java JDK8
安装openjdk1.更新软件包列表: sudo apt-get update 2.安装openjdk-8-jdk: sudo apt-get install openjdk-8-jdk 3.查看ja ...
- 【Python学习之五】高级特性4(切片、迭代、列表生成器、生成器、迭代器)
4.生成器(generator) 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的 ...
- 如何用纯 CSS 和 D3 创作一艘遨游太空的宇宙飞船
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/oMqNmv 可交互视频 ...
- 如何用纯 CSS 创作一台拍立得照相机
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/YjYgey 可交互视频 此视频是可 ...