[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
[算法]博弈论+二分图匹配(最大流) [题解]方格图黑白染色得到二分图, 二分图博弈:当起点不属于某个最大匹配时,后手必胜. 问题转化为那些点不属于某个最大匹配. 先找到一个最大匹配,非匹配点加入答案 ...
随机推荐
- idea css文件不识别的问题的解决方案
可以看到 progressBar不识别 发现仅仅是这一个文件名不识别 所以换一个任意别的文件名即可识别
- elasticsearch对某段时间范围内按时间间隔进行统计
{ "query" : { "constant_score" : { "filter" : { "range" : { ...
- Django之Models的class Meta
模型元数据是“任何不是字段的数据”,比如排序选项(ordering),数据库表名(db_table)或者人类可读的单复数名称(verbose_name 和verbose_name_plural).在模 ...
- Spring学习(四)-----Spring Bean引用同xml和不同xml bean的例子
在Spring,bean可以“访问”对方通过bean配置文件指定相同或不同的引用. 1. Bean在不同的XML文件 如果是在不同XML文件中的bean,可以用一个“ref”标签,“bean”属性引用 ...
- flask ssti python2和python3 注入总结和区别
总结一下flask ssti的注入语句 代码 import uuid from flask import Flask, request, make_response, session,render_t ...
- NO.2:自学python之路------变量类型、列表、字典
引言 本周初步认识了库,并学习了Python中各种类型的变量和常用操作.并完成了较为完善的用户与商家购物界面设计. 正文 模块: Python有标准库和第三方库.第三方库需要安装才能使用.大量的库可以 ...
- 关于XML文档操作类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.X ...
- Swing State: Consistent Updates for Stateful and Programmable Data Planes
Swing State: Consistent Updates for Stateful and Programmable Data Planes 年份:2017 来源:ACM 本篇论文解决的问题 B ...
- Log4Net的使用研究(一)
等待研究中………… 20160421 标题:C#使用Log4Net记录日志 文章地址: http://www.cnblogs.com/wangsaiming/archive/2013/01/11/ ...
- lintcode-407-加一
407-加一 给定一个非负数,表示一个数字数组,在该数的基础上+1,返回一个新的数组. 该数字按照大小进行排列,最大的数在列表的最前面. 样例 给定 [1,2,3] 表示 123, 返回 [1,2,4 ...