【LOJ6033】棋盘游戏【二分图博弈】
传送门
显然是个二分图,设开始位置是左边,另一边是右边
那么先手是把左边挪到右边,后手是把右边挪到左边,不能挪的那方失败
结论:Alice必胜当且仅当开始位置不一定在最大匹配上
必要性:
如果开始位置不在最大匹配上,那一定有种匹配方案不包含开始位置(废话)
考虑这种方案,由于左边已经空出来了,所以右边和它连通的点都已经有匹配。
这样Bob移动到哪里,Alice就移到它的匹配点,这样Alice必胜。
充分性:
考虑逆否命题,如果开始位置一定在最大匹配上,那么Bob必胜。
①如果右边有和开始位置相邻的未匹配点
Bob移到这个位置,然后转换为了上面的情况
②如果没有
那就移到匹配点
因为开始点一定在最大匹配上,所以移了之后找不到未匹配点
同理后面如果左边有未匹配点就找到了一条增广路,矛盾
这样可以一直走匹配点直到胜利
所以先跑个最大匹配,从未匹配点开始dfs,对所有与之相邻点给匹配点打上标记
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#define MAXN 10005
#define MAXM 50005
using namespace std;
struct edge{int u,v;}e[MAXM];
int head[MAXN],nxt[MAXM],cnt;
void addnode(int u,int v)
{e[++cnt]=(edge){u,v};nxt[cnt]=head[u];head[u]=cnt;
}
int n,m;
char s[105][105];
#define id(x,y) (((x)-1)*m+(y))
const int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
int link[MAXN],used[MAXN];
bool find(int u,int mark)
{for (int i=head[u];i;i=nxt[i])if (used[e[i].v]!=mark){used[e[i].v]=mark;if (!link[e[i].v]||find(link[e[i].v],mark)) return link[e[i].v]=u,true;}return false;
}
bool ans[MAXN];
void dfs(int u)
{for (int i=head[u];i;i=nxt[i])if (!ans[link[e[i].v]]){ans[link[e[i].v]]=true;dfs(link[e[i].v]);}
}
int main()
{scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) scanf("%s",s[i]+1);for (int x=1;x<=n;x++)for (int y=1;y<=m;y++)if (s[x][y]=='.'&&(x+y)&1)for (int i=0;i<4;i++)if (s[x+dx[i]][y+dy[i]]=='.')addnode(id(x,y),id(x+dx[i],y+dy[i]));int d=0;for (int x=1;x<=n;x++)for (int y=1;y<=m;y++)if (s[x][y]=='.'&&(x+y)&1)d+=find(id(x,y),id(x,y)),ans[id(x,y)]=1;cerr<<d<<endl;for (int x=1;x<=n;x++)for (int y=1;y<=m;y++)if (s[x][y]=='.'&&!((x+y)&1))link[id(x,y)]? ans[link[id(x,y)]]=0,link[link[id(x,y)]]=id(x,y):ans[id(x,y)]=1;int tcnt=cnt;for (int i=1;i<=tcnt;i++) addnode(e[i].v,e[i].u);for (int i=1;i<=n*m;i++) if (ans[i]) dfs(i);int tot=0;for (int x=1;x<=n;x++)for (int y=1;y<=m;y++)tot+=ans[id(x,y)];printf("%d\n",tot);for (int x=1;x<=n;x++)for (int y=1;y<=m;y++)if (ans[id(x,y)])printf("%d %d\n",x,y);return 0;
}
【LOJ6033】棋盘游戏【二分图博弈】相关推荐
- BZOJ 1443 二分图博弈 网络流
思路: 二分图博弈嘛 找到最大匹配的必须点 跑个网络流 前后DFS一遍 //By SiriusRen #include <queue> #include <cstdio> #i ...
- [NOI2011]兔兔与蛋蛋游戏 二分图博弈
题面 题面 题解 通过观察,我们可以发现如下性质: 可以看做是2个人在不断移动空格,只是2个人能移动的边不同 一个位置不会被重复经过 : 根据题目要求,因为是按黑白轮流走,所以不可能重复经过一个点,不 ...
- 2020CCPC(长春) - Combination Lock(二分图博弈)
题目大意:给出一个密码锁,两个人一起玩游戏,给出初始的密码,规定: 每一次都可以转动一个位置的数字一个单位 不可以转动到已经出现过的数字 不可以转动到被 ban 掉的数字 无法转动的人视为失败,问谁能 ...
- 【NOI2011】兔兔与蛋蛋的游戏【二分图博弈】
传送门 结论 不会有同一个棋子移动两次 反证法,对于第一个移动第二次的棋子 设两次移动之间(含)的移动的棋子为A1,A2,A3,--,AnA_1,A_2,A_3,--,A_nA1,A2,A3,- ...
- 博弈论题表(好少~~~)
bzoj2017:[Usaco2009 Nov]硬币游戏 *用了一小点思想的傻逼dp(记忆化搜索) bzoj1188:[HNOI2007]分裂游戏 **很神奇的把游戏拆分为子游戏的方法 bzoj102 ...
- Contest Record
Contest 1135 at HZOI Problem A: 优美的棋 发现一个可以证明的规律就是了-- 忘记给<<运算的左边变量转化为long long类型了,结果挂了20分-- 以后 ...
- bzoj2437 [Noi2011]兔兔与蛋蛋
二分图博弈果然都是一个套路,必经点必胜,非必经点必败, 但是肯定不能每走一步就重新建图判断必胜还是必败,那么我们可以这样:每走一步就把这个点删掉,然后find他原来的匹配,如果找不到,就说明他是必经点 ...
- NOI2010~NOI2018选做
[NOI2010] [NOI2010]海拔 高度只需要0/1,所以一个合法方案就是一个割,平面图求最小割. [NOI2010]航空管制 反序拓扑排序,每次取出第一类限制最大的放置,这样做答案不会更劣. ...
- 一些有难度的网络流问题
本质是线性规划 最小割建模 NOI2010 海拔 一个的网格,每跳变的两个方向都有一定数目的人流,每个格点都有海拔,一个人爬坡需要付出高度差的代价,下坡不付出代价,左下角高度为,右上角高度为,求安排其 ...
最新文章
- 小猿圈html5教程之canvas绘制线段方法
- PowerDesigner如何导出建表sql脚本(转)
- 微信小程序—day02
- 现代软件工程 作业 第一周博客作业
- 还在家隔离呢?没事写写这些程序吧!
- hadoop搭建之hadoop安装
- html横菜单中菜单均匀分布,html – 如何在flexbox中的行间均匀分布元素?
- 用Podman来代替Docker Desktop
- 面试常见的26个问题
- Python游戏嗷大喵快跑设计
- Python与OpenCV(二)——基于背景差分法的运动目标检测程序分析
- 孙溟㠭创作篆刻作品(稻)纪念袁隆平老先生
- 滞胀世代 (ZT) 作者:bystander
- 常用的excel公式备忘
- python的flask框架
- Ubuntu 16.04 LTS安装sogou输入法详解
- XX健康:预约管理-预约设置日历插件文件简单下载Excel文件解析Excel表数据批量导入
- RFID技术在固定资产管理中的作用
- 思科nexus虚拟交换之开机初始化配置(Nexus7K、Nexus5K等)
- xp系统怎样访问校园网服务器,有线校园网电脑连接教程
热门文章
- 她半年内举报了755篇问题论文,专挑中国“下手”?还牵扯到北大副校长.........
- 一个富二代仅凭“1+1”就压制了全世界的数学家两个世纪......
- 用MATLAB三步完成机器人搭建
- 不作死就不会死,盘点那些死于自己发明的发明家
- 渤海发现大油田,证券会提示风险,微博回应流量造假,刘国梁制定史上最严奖惩体系,这就是今天的大新闻。...
- 风靡全球的人工智能,如何赶上这班车?
- 重磅来袭,2018 年 6 月编程语言排行榜
- 姑娘,你为什么要编程?
- 计算机视觉招聘_INDEMIND|SLAM、计算机视觉、深度学习算法招聘(社招实习)
- 用linux命令通常做什么,如何知道你在 Linux 里最常使用的几个命令?