[JSOI2009]游戏 二分图博弈
题面
题解
二分图博弈的模板题,只要会二分图博弈就可以做了,可以当做板子打。
根据二分图博弈,如果一个点x在某种方案中不属于最大匹配,那么这是一个先手必败点。
因为对方先手,因此我们就是要找这样一个点。
观察点x的性质,对于这样一个点x,我们一定可以找到一个点来代替它的位置,而什么样的点可以代替它呢?
从x出发,能够到达的未匹配同侧点可以,只需要交换匹配边即可。
因此做几遍dfs就可以了
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 110
#define ac 81000//向四周连边
int n, m, num;
int Head[ac], Next[ac], date[ac], tot;
int link[ac], match[ac], id[AC][AC], a[6] = {-1, 1, 0, 0}, b[6] = {0, 0, -1, 1};
char s[AC][AC];
bool vis[ac], z[ac];
struct node{int x, y;}back[ac];
inline void add(int f, int w)
{
date[++ tot] = w, Next[tot] = Head[f], Head[f] = tot;
date[++ tot] = f, Next[tot] = Head[w], Head[w] = tot;
}
bool dfs(int x)
{
for(R i = Head[x]; i; i = Next[i])
{
int now = date[i];
if(vis[now]) continue;
vis[now] = true;
if(!link[now] || dfs(link[now]))
{
link[now] = x, match[x] = now;
return 1;
}
}
return 0;
}
void cal()
{
memset(link, 0, sizeof(link));
for(R i = 1; i <= num; i ++)
{
if(!(i & 1)) continue;//每次都是从S集合出发的
memset(vis, 0, sizeof(vis)), dfs(i);//不需要知道最大匹配的大小,只需要知道某一种合法方案即可
}
}
void pre()
{
scanf("%d%d", &n, &m), num = n * m;
for(R i = 1; i <= n; i ++) scanf("%s", s[i] + 1);
int tmp1 = 1, tmp2 = 2;
for(R i = 1; i <= n; i ++)
{
for(R j = 1; j <= m; j ++)
{
if((i + j) & 1) id[i][j] = tmp2, back[tmp2] = (node){i, j}, tmp2 += 2;
else id[i][j] = tmp1, back[tmp1] = (node){i, j}, tmp1 += 2;
}
}
for(R i = 1; i <= n; i ++)
for(R j = 1; j <= m; j ++)
{
if(s[i][j] == '#') continue;
for(R k = 0; k <= 3; k ++)
{
int x = i + a[k], y = j + b[k];
if(x <= 0 || x > n || y <= 0 || y > m || s[x][y] == '#') continue;
int s = id[i][j], t = id[x][y];
(s & 1) ? add(s, t) : add(t, s);//由编号为奇数的点向编号为偶数的点连边
}
}
}
void dfs1(int x)
{
if(z[x]) return ;
z[x] = true;
for(R i = Head[x]; i; i = Next[i]) dfs1(link[date[i]]);//这样才能保证dfs到的是同侧的点,
}//只有同侧的点才能保证经过的匹配边和非匹配边数量相同,可以互相交换
void dfs2(int x)
{
if(z[x]) return ;
z[x] = true;
for(R i = Head[x]; i; i = Next[i]) dfs2(match[date[i]]);
}
void work()
{
for(R i = 1; i <= num; i ++)
{
if(s[back[i].x][back[i].y] == '#') continue;
if((i & 1) && !match[i]) dfs1(i);
else if(!(i & 1) && !link[i]) dfs2(i);//注意要从同侧的非匹配点dfs到同侧的匹配点,这样才能互换方案
}
bool done = false;
for(R i = 1; i <= n; i ++)
for(R j = 1; j <= m; j ++)
if(z[id[i][j]]) {done = true; break;}
if(!done) {printf("LOSE\n"); return ;}
printf("WIN\n");
for(R i = 1; i <= n; i ++)
for(R j = 1; j <= m; j ++)
if(z[id[i][j]]) printf("%d %d\n", i, j);
/* for(R i = 1; i <= num; i ++) if(z[i]) {done = true; break;}
if(!done) {printf("LOSE\n"); return ;}
printf("WIN\n");
for(R i = 1; i <= num; i ++)
if(z[i]) printf("%d %d\n", back[i].x, back[i].y);*/
}
int main()
{
// freopen("in.in", "r", stdin);
pre();
cal();
work();
// fclose(stdin);
return 0;
}
[JSOI2009]游戏 二分图博弈的更多相关文章
- [NOI2011]兔兔与蛋蛋游戏 二分图博弈
题面 题面 题解 通过观察,我们可以发现如下性质: 可以看做是2个人在不断移动空格,只是2个人能移动的边不同 一个位置不会被重复经过 : 根据题目要求,因为是按黑白轮流走,所以不可能重复经过一个点,不 ...
- [luogu1971 NOI2011] 兔兔与蛋蛋游戏 (二分图博弈)
传送门 Solution 补一篇二分图博弈 这个博客写的很详细qwq: https://www.cnblogs.com/maijing/p/4703094.html Code //By Menteur ...
- BZOJ 1443 游戏(二分图博弈)
新知识get. 一类博弈问题,基于以下条件: 1.博弈者人数为两人,双方轮流进行决策.2.博弈状态(对应点)可分为两类(状态空间可分为两个集合),对应二分图两边(X集和Y集).任意合法的决策(对应边) ...
- luogu4055 游戏 (二分图博弈)
考虑对非障碍的点黑白染色然后做二分图最大匹配,那么有结论,先手必胜当且仅当不是完美匹配,而且可以放的点是那些可以不匹配的点 从非匹配点开始走,后手只能走到匹配点,于是先手就可以走匹配边.由于不能走走过 ...
- BZOJ.2437.[NOI2011]兔兔与蛋蛋游戏(二分图博弈 匈牙利)
题目链接 首先空格的移动等价于棋子在黑白格交替移动(设起点移向白格就是黑色),且不会走到到起点距离为奇数的黑格.到起点距离为偶数的白格(删掉就行了),且不会重复走一个格子. (然后策略就同上题了,只不 ...
- [模板] 二分图博弈 && BZOJ2463:[中山市选2009]谁能赢呢?
二分图博弈 from BZOJ 1443 游戏(二分图博弈) - free-loop - 博客园 定义 1.博弈者人数为两人,双方轮流进行决策. 2.博弈状态(对应点)可分为两类(状态空间可分为两个集 ...
- BZOJ1443: [JSOI2009]游戏Game
如果没有不能走的格子的话,和BZOJ2463一样,直接判断是否能二分图匹配 现在有了一些不能走的格子 黑白染色后求出最大匹配 如果是完备匹配,则无论如何后手都能转移到1*2的另一端,故先手必输 否则的 ...
- JSOI2009 游戏
1443: [JSOI2009]游戏Game Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 557 Solved: 251[Submit][Stat ...
- 【BZOJ】1443: [JSOI2009]游戏Game
[算法]博弈论+二分图匹配(最大流) [题解]方格图黑白染色得到二分图, 二分图博弈:当起点不属于某个最大匹配时,后手必胜. 问题转化为那些点不属于某个最大匹配. 先找到一个最大匹配,非匹配点加入答案 ...
随机推荐
- 探究linux设备驱动模型之——platform虚拟总线(三)最终章
这篇是最终章了,结束这一章后,对于platform平台总线驱动的使用方法应该是能够无压力掌握.但是这一章涉及的内容会比前面两章多一些. 我们会一步一步地来完善上一章的例子.完善的目的是能够在应用层去控 ...
- 常用常忘的delegate,记一下。
多线程: 1 new Thread(new ThreadStart(Method1))).Start(); 1 new Thread(new ParameterizedThreadStart(Meth ...
- Linux大全
Linux 基本指令介紹 一定要先學會的指令:ls, more, cd, pwd, rpm, ifconfig, find 登入與登出(開機與關機):telnet, login, exit, sh ...
- CMDBuild2.4.3安装配置
参考文档: 官网:http://www.cmdbuild.org/en 参考:http://blog.csdn.net/shawn210/article/details/70230248 本文涉及CM ...
- [python] Queue.Queue vs. collections.deque
https://stackoverflow.com/questions/717148/queue-queue-vs-collections-deque/717199#717199 Queue,Queu ...
- Maven私有仓库搭建以及使用
一.使用Docker安装Nexus Docker search nexus docker pull docker.io/sonatype/nexus3 mkdir -p /usr/local/nexu ...
- JDBC及DBUtils
1.JDBC2.DBUtils ###01JDBC概念和数据库驱动程序 * A: JDBC概念和数据库驱动程序 * a: JDBC概述 * JDBC(Java Data Base Connectivi ...
- HTML5+Bootstrap 学习笔记 4
HTML5 <map> <area> 标签 <map> 标签定义客户端的图像映射.图像映射是带有可点击区域的图像. <area> 标签定义图像映射内部的 ...
- 第10次Scrum会议(10/22)【欢迎来怼】
一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华小组照片 二.开会信息 时间:2017/10/22 17:20~17:33,总计13min.地点:东北师范 ...
- “我爱淘”第二冲刺阶段Scrum站立会议7
完成任务: 完成学院分类的点击查看书籍功能,可以点击书的条目查看书的详细信息.将登陆界面以及注册发布界面完善了一下修复一些bug. 计划任务: 将书的详细信息进行完善,并且可以点击收藏以及已预订等功能 ...