BZOJ1443 [JSOI2009]游戏Game 【博弈论 + 二分图匹配】
题目链接
题解
既然是网格图,便可以二分染色
二分染色后发现,游戏路径是黑白交错的
让人想到匹配时的增广路
后手要赢【指移动的后手】,必须在一个与起点同色的地方终止
容易想到完全匹配的图先手是必胜的,因为完全匹配的图要么走到对面终止,要么从对面找一条非匹配边走回来,而由于是完全匹配,总能继续走下去,所以先手总能走到一个不同色点
于是乎对于一个匹配完的二分图,我们从一个未匹配的点出发,此时先手只能走未匹配边,而由于已经是匹配完毕,所以走到的点一定是已匹配的点,此时我们可以继续走到该点的匹配点,先手要么无法操作,要么继续走一条未匹配边
换言之,我们走的总是交错边,而交错边上的匹配情况是可以互换的,所以从一个未匹配的点出发能走到的同侧的点都是后手必胜的
也不知道为什么\(O(n^3)\)怎么能跑\(10^4\)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 10005,maxm = 1000005,INF = 1000000000;
inline int read(){
	int out = 0,flag = 1; char c = getchar();
	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
	return out * flag;
}
int N,M,n,cnt;
int h[maxn],ne;
struct EDGE{int to,nxt;}ed[maxm];
inline void build(int u,int v){
	ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
	ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
char s[105][105];
int id[105][105],c[maxn],x[maxn],y[maxn];
void dfs1(int u){
	Redge(u) if (c[to = ed[k].to] == -1)
		c[to] = c[u] ^ 1,dfs1(to);
}
int lk[maxn],vis[maxn],ok[maxn];
bool find(int u){
	Redge(u) if (!vis[to = ed[k].to]){
		vis[to] = true;
		if (!lk[to] || find(lk[to])){
			lk[to] = u;
			return true;
		}
	}
	return false;
}
void dfs(int u){
	if (ok[u]) return;
	ok[u] = true;
	Redge(u) if (lk[to = ed[k].to]) dfs(lk[to]);
}
inline bool cmp(const int& a,const int& b){
	return x[a] == x[b] ? y[a] < y[b] : x[a] < x[b];
}
int main(){
	N = read(); M = read();
	REP(i,N){
		scanf("%s",s[i] + 1);
		REP(j,M) if (s[i][j] == '.') id[i][j] = ++n,x[n] = i,y[n] = j;
	}
	REP(i,N) REP(j,M){
		if (!id[i][j]) continue;
		if (id[i + 1][j]) build(id[i][j],id[i + 1][j]);
		if (id[i][j + 1]) build(id[i][j],id[i][j + 1]);
	}
	REP(i,n) c[i] = -1;
	REP(i,n) if (c[i] == -1) c[i] = 0,dfs1(i);
	REP(i,n) if (c[i]) cls(vis),cnt += find(i);
	if (cnt * 2 == n){puts("LOSE"); return 0;}
	REP(i,n) if (!c[i]) lk[lk[i]] = i;
	REP(i,n) if (!lk[i]) dfs(i);
	puts("WIN");
	REP(i,n) if (ok[i]) printf("%d %d\n",x[i],y[i]);
	return 0;
}
												
											BZOJ1443 [JSOI2009]游戏Game 【博弈论 + 二分图匹配】的更多相关文章
- BZOJ:[JSOI2009]游戏Game【二分图匹配乱搞】
		
题目大意:n*m的棋盘,其中有些区域是禁区,两个人在棋盘上进行博弈,后手选择棋子的初始位置,然后先后手轮流将棋子往上下左右移动,走过的区域不能再走,问能否有一个位置使得后手必胜 Input 输入数据首 ...
 - BZOJ1443: [JSOI2009]游戏Game
		
如果没有不能走的格子的话,和BZOJ2463一样,直接判断是否能二分图匹配 现在有了一些不能走的格子 黑白染色后求出最大匹配 如果是完备匹配,则无论如何后手都能转移到1*2的另一端,故先手必输 否则的 ...
 - 【BZOJ1443】[JSOI2009]游戏Game(二分图+博弈)
		
BZOJ 题意: 给出一个\(n*m\)的网格,其中有一些障碍点. 现在两个人玩游戏,首先先手选定一个点,然后从后手开始轮流移动,不能移动者即输掉这次游戏. 规定不能移动到那些之前已经到过的格子上. ...
 - BZOJ 1443 [JSOI2009]游戏Game ——博弈论
		
好题. 首先看到棋盘,先黑白染色. 然后就是二分图的经典模型. 考虑最特殊的情况,完美匹配,那么先手必胜, 因为无论如何,先手走匹配边,后手无论走哪条边,总有对应的匹配边. 如果在不在最大匹配中出发, ...
 - BZOJ2437 [Noi2011]兔兔与蛋蛋  【博弈论 + 二分图匹配】
		
题目链接 BZOJ2437 题解 和JSOI2014很像 只不过这题动态删点 如果我们把空位置看做\(X\)的话,就会发现我们走的路径是一个\(OX\)交错的路径 然后将图二分染色,当前点必胜,当且仅 ...
 - 【BZOJ】1443: [JSOI2009]游戏Game
		
[算法]博弈论+二分图匹配(最大流) [题解]方格图黑白染色得到二分图, 二分图博弈:当起点不属于某个最大匹配时,后手必胜. 问题转化为那些点不属于某个最大匹配. 先找到一个最大匹配,非匹配点加入答案 ...
 - 【BZOJ1443】游戏(二分图匹配,博弈论)
		
[BZOJ1443]游戏(二分图匹配,博弈论) 题面 BZOJ 题解 很明显的二分图博弈问题. 发现每次移动一定是从一个黑点到达一个白点,或者反过来. 所以可以对于棋盘进行染色然后连边. 考虑一下必胜 ...
 - 博弈论(二分图匹配):NOI 2011 兔兔与蛋蛋游戏
		
Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...
 - BZOJ-1854   游戏     二分图匹配 (并查集)
		
1854: [Scoi2010]游戏 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 3372 Solved: 1244 [Submit][Status] ...
 
随机推荐
- 最安全的聊天工具——Cryptocat
			
关于Cryptocat Cryptocat 是啥?Cryptocat,俗称 "加密猫",是一款非常注重安全的聊天软件. 美国前中情局员工斯诺登在躲避美国政府追捕过程中,就是使用 C ...
 - 服务器与Linux操作系统基础原理
			
1.服务器 2.Linux操作系统 1. 服务器 服务器定义与分类: 定义:一个管理资源并为用户提供服务的计算机软件. 按应用分类:通常分为文件服务器(能使用户在其它计算机访问文件),数据库服务器和应 ...
 - Plasma Cash 合约解读
			
作者介绍 虫洞社区·签约作者 steven bai Plasma Cash 合约解读 Plasma Cash 合约解读 1. 合约代码 2. 合约文件简单介绍 3. Plasma Cash 的基础数据 ...
 - python中__name__属性的使用
			
python常用模块目录 1.打印出函数名字而非函数名对应的地址 )打印的是函数地址 def func(): print("我是%s函数"%func) func() ------- ...
 - 最小费用最大流模板(POJ 2135-Farm Tour)
			
最近正好需要用到最小费用最大流,所以网上就找了这方面的代码,动手写了写,先在博客里存一下~ 代码的题目是POJ2135-Farm Tour 需要了解算法思想的,可以参考下面一篇文章,个人觉得有最大流基 ...
 - excel中如何将时间戳转换为日期格式
			
https://www.cnblogs.com/xueluozhangxin/p/5868225.html =TEXT((B2/1000+8*3600)/86400+70*365+19,"y ...
 - Daily Scrum9 11.13
			
昨天的任务已完成. 今日任务: 姓名 今日任务 时长 徐钧鸿 测试SQL包里的代码 2h 张艺 继续搭建还没搭建完的框架 修复bug 2h 黄可嵩 继续进行搜索响应编写 2h 徐方宇 搭建框架 修改b ...
 - Daily Scrum (2015/11/5)
			
这天晚上我们对爬虫进行了一些测试,发现仍然存在一些不小的BUG.现在我们的爬虫已经能完成基本的功能,焉域政同学也正在把他之前写的分类功能继续完善.在BUG的测试中,我们发现如果要求爬虫爬取特定的文件类 ...
 - 【每日scrum】第一次冲刺day3
			
学习安卓,和小伙伴讨论百度API调用的问题,最后决定自己写地图
 - Python写一个根据日期计算是星期几的模块
			
import datetimedef get_week_day(date): week_day = { 0: '星期一', 1: '星期二', 2: '星期三', 3: '星期四', 4: '星期五' ...