BZOJ:[JSOI2009]游戏Game【二分图匹配乱搞】
题目大意:n*m的棋盘,其中有些区域是禁区,两个人在棋盘上进行博弈,后手选择棋子的初始位置,然后先后手轮流将棋子往上下左右移动,走过的区域不能再走,问能否有一个位置使得后手必胜
Input
输入数据首先输入两个整数N,M,表示了迷宫的边长。 接下来N行,每行M个字符,描述了迷宫。
Output
若小AA能够赢得游戏,则输出一行"WIN",然后输出所有可以赢得游戏的起始位置,按行优先顺序输出 每行一个,否则输出一行"LOSE"(不包含引号)。
Sample Input
3 3
.##
...
#.#
Sample Output
2 3
3 2
HINT
对于100%的数据,有1≤n,m≤100。
对于30%的数据,有1≤n,m≤5。
Source
完成二分图这章绝对有必要做的一题
思路:如果没有禁区,那这题就沦为了这题:http://hi.baidu.com/lov_zyf/item/04fa260e7b3ba41acc34eaff [中山市选2009]谁能赢呢?
唔 分奇偶讨论就行,那有禁区怎么办?其实可以从上面那题收到启发,就是1*2的骨牌的覆盖问题,然后大白书二分图匹配那章那个经典的博弈也是解开这题的关键
显然如果棋盘能完全被1*2骨牌覆盖,那么后手必输,因为先手总能移动到骨牌的另一端,如果不能被完全覆盖呢?只要将棋子放在没被覆盖的那点就行了,先手第一步一定移动到一个骨牌里去,先后手交换
间二染色后,这个问题成了二分图匹配的问题,只要初始位置是一个未盖点,那么后手一定能沿着增光轨走下去,因此后手必胜
那么判断出胜负后接下来问题就是哪些位置可能成为初始位置,基于上面的讨论这个点一定是可能成为未盖点的点(因为二分图的最大匹配可能有很多种样子,虽然匹配数相同)
最直观的方法应该是:考虑一个点如果一定在最大匹配里(也就是不可能成为初始点)那么将这个点删除,其它边不变做一次匈牙利,看最大匹配数是否改变,但这是个显然超时的做法
于是我考虑一个y部的点时,保留之前做过的最短路,把这点标记掉,如果之前和y部这个点匹配的点能继续增广,也就是在最大匹配保持不变的情况下,这个点能和新的点匹配,那这个y部的点就是可有可无的了,也就是可以成为未盖点
------------------------------------------------------------------------------------------------------------
顺便做完后百度了下题解,发现做法真多!二分图那部边基本是相同的思路,考虑哪些点可能成为未盖点的时候有沿着增广轨DFS的,有网络流的,而且速度都比我快,果然还是too young
#include <stdio.h>
#include <iostream>
#include<queue>
#include <string.h>
#include <algorithm>
#define maxn 200000
#define maxm 1000005
#define inf 0x3f3f3f3f
using namespace std;
const int dx[10]={0,0,0,1,-1};
const int dy[10]={0,1,-1,0,0};
int next[maxn],head[maxn],now,point[maxn];
int match[maxn],x[maxn],y[maxn],mat[maxn];
bool visit[maxn],mark[maxn];
char ch[200][200];
void add(int x,int y)
{
next[++now]=head[x];
head[x]=now;
point[now]=y;
}
int dfs(int k)
{
for(int i=head[k];i;i=next[i])if(!visit[point[i]])
{
int u=point[i];
visit[u]=1;
if(dfs(match[u])||match[u]==-1)
{
match[u]=k;
mat[k]=u;
return 1;
}
}
return 0;
}
int main()
{
int n,m,u=0,v=0,flag=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%s",ch[i]+1);
int fi=0;
for(int i=1;i<=n;i++)
{
fi^=1;
for(int j=fi+1;j<=m;j+=2)if(ch[i][j]=='.')
{
x[++u]=i*m+j;
for(int k=1;k<=4;k++)
{
int xx=i+dx[k],yy=j+dy[k];
if(ch[xx][yy]=='.')
{
add(i*m+j,xx*m+yy);
add(xx*m+yy,i*m+j);
}
}
}
}
fi=1;
for(int i=1;i<=n;i++)
{
fi^=1;
for(int j=fi+1;j<=m;j+=2)
if(ch[i][j]=='.')y[++v]=i*m+j;
}
memset(match,-1,sizeof(match));
for(int i=1;i<=u;i++)
{
memset(visit,0,sizeof(visit));
if(!dfs(x[i]))
{flag=1;mark[x[i]]=1;}
}
for(int i=1;i<=v;i++)
{
if(match[y[i]]==-1){mark[y[i]]=1;flag=1;}
else
{
memset(visit,0,sizeof(visit));
visit[y[i]]=1;
if(dfs(match[y[i]]))
{match[y[i]]=-1;mark[y[i]]=1;flag=1;}
}
}
for(int i=1;i<=v;i++)
{
memset(visit,0,sizeof(visit));
if(!dfs(y[i]))
{flag=1;mark[y[i]]=1;}
}
for(int i=1;i<=u;i++)
{
if(match[x[i]]==-1){mark[x[i]]=1;flag=1;}
else
{
memset(visit,0,sizeof(visit));
visit[x[i]]=1;
if(dfs(match[x[i]]))
{match[x[i]]=-1;mark[x[i]]=1;flag=1;}
}
}
if(flag==1)printf("WIN\n");else{printf("LOSE\n");return 0;}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mark[i*m+j])printf("%d %d\n",i,j);
}
}
return 0;
}
BZOJ:[JSOI2009]游戏Game【二分图匹配乱搞】的更多相关文章
- 【BZOJ1443】游戏(二分图匹配,博弈论)
[BZOJ1443]游戏(二分图匹配,博弈论) 题面 BZOJ 题解 很明显的二分图博弈问题. 发现每次移动一定是从一个黑点到达一个白点,或者反过来. 所以可以对于棋盘进行染色然后连边. 考虑一下必胜 ...
- 【BZOJ4554】游戏(二分图匹配,网络流)
[BZOJ4554]游戏(二分图匹配,网络流) 题解 Description 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若干个炸弹,看 是否能炸到对手, ...
- BZOJ_4554_[Tjoi2016&Heoi2016]游戏_二分图匹配
BZOJ_4554_[Tjoi2016&Heoi2016]游戏_二分图匹配 Description 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若 ...
- BZOJ 1854: [Scoi2010]游戏(二分图匹配/并查集)
题面: https://www.lydsy.com/JudgeOnline/problem.php?id=1854 题解: 1.二分图匹配: 首先我们发现每件装备只能在两种属性中选一种.因此,我们以每 ...
- BZOJ 1059 [ZJOI2007]矩阵游戏:二分图匹配
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1059 题意: 给你一个n*n的01矩阵. 你可以任意次地交换某两行或某两列. 问你是否可以 ...
- [SCOI2010]连续攻击游戏 BZOJ1854 二分图匹配
题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备 ...
- BZOJ1854:游戏(二分图匹配)
lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使 ...
- [BZOJ1059]:[ZJOI2007]矩阵游戏(二分图匹配)
题目传送门 题目描述 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N×N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种 ...
- BZOJ.3140.[HNOI2013]消毒(二分图匹配 匈牙利)
题目链接 不难想到每次一定是切一片. 如果是平面,很容易想到直接做二分图匹配.对于3维的? 可以发现min(a,b,c)的最大值只有\(\sqrt[3]{n}≈17\),我们暴力枚举这一最小值代表的是 ...
随机推荐
- Pycharm中pygame报错
什么鬼???我记得刚安装过啊-.. 并且本机只有一个python3.5,环境变量之前都是正常,我去折腾了大半天,原来在pycharm中安装模块是在如下所示图中 以后如果没有安装模块,都可以在这里进行安 ...
- Jquery 操作HTML5自定义属性data-*
HTML5自定义属性规范的写法<a data-roleid="12"></a>,也可以直接写<a roleid="12">& ...
- qconbeijing2017
http://2017.qconbeijing.com/schedule 第一天 (2017年4月16日/星期日) 签到 专题 主题演讲 快速进化的容器生态 微服务与 DevOps 最佳实践(厂商 ...
- 几种创建线程方式Thread类和Runnable接口
对于很多想学习java的人来说,经常听别人说线程难,其实真正理解了线程后,一点都不会觉得线程难,这里我为大家梳理下线程的创建方式吧. 一.线程的创建方式有三种 1.继承Thread类 2.实现Runn ...
- 开发笔记 - 解决font-awesome等图标在浏览器中的兼容问题
今天在写前端页面的时候,觉得font-awesome简单实用就上手试了一下,因为font-awesome图标库甚为强大,我就在其css上多做了一些尝试,这一尝试发现了一个致命的问题,当我对i标签进行统 ...
- 什么是cookie(前段时间看到别人简历上把cookie和localStorage混淆了所以专门又去了解了下)
在前端面试中,有一个必问的问题:请你谈谈cookie和localStorage有什么区别啊? localStorage是H5中的一种浏览器本地存储方式,而实际上,cookie本身并不是用来做服务器存储 ...
- Python3简明教程(一)—— 开始Python之旅
第一个Python程序 作为我们第一个Python程序——打印"Hello World!". 在终端输入Python3进入交互界面: 输入print("Hello W ...
- 【2019-5-26】python:字典、常用字符串处理方法及文件操作
一.数据类型:字典 1.字典: 1.1定义字典:dict={'key':'value'} 1.2字典与列表相比,字典取值快,可直接找到key 1.3字典是无序的,不能根据顺序取值 1.4多个元素用逗号 ...
- 企业支付宝账号开发接口教程--JAVA-UTF-8(实际操作完善中...SpringMVC+JSP)
关于即时到账的开发.审核通过.简单测试如下. 希望看的可以收藏或者赞一下哦. 1:拥有自己的支付宝企业账号.去产品商店选择适合自己的方案.并签约合同. 2:选择合适的商家收款产品并去签约.填写相应的信 ...
- luogu P1519 穿越栅栏 Overfencing
题目描述 描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫.幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口.更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意 ...