题面

题面

题解

二分图博弈的模板题,只要会二分图博弈就可以做了,可以当做板子打。

根据二分图博弈,如果一个点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]游戏 二分图博弈的更多相关文章

  1. [NOI2011]兔兔与蛋蛋游戏 二分图博弈

    题面 题面 题解 通过观察,我们可以发现如下性质: 可以看做是2个人在不断移动空格,只是2个人能移动的边不同 一个位置不会被重复经过 : 根据题目要求,因为是按黑白轮流走,所以不可能重复经过一个点,不 ...

  2. [luogu1971 NOI2011] 兔兔与蛋蛋游戏 (二分图博弈)

    传送门 Solution 补一篇二分图博弈 这个博客写的很详细qwq: https://www.cnblogs.com/maijing/p/4703094.html Code //By Menteur ...

  3. BZOJ 1443 游戏(二分图博弈)

    新知识get. 一类博弈问题,基于以下条件: 1.博弈者人数为两人,双方轮流进行决策.2.博弈状态(对应点)可分为两类(状态空间可分为两个集合),对应二分图两边(X集和Y集).任意合法的决策(对应边) ...

  4. luogu4055 游戏 (二分图博弈)

    考虑对非障碍的点黑白染色然后做二分图最大匹配,那么有结论,先手必胜当且仅当不是完美匹配,而且可以放的点是那些可以不匹配的点 从非匹配点开始走,后手只能走到匹配点,于是先手就可以走匹配边.由于不能走走过 ...

  5. BZOJ.2437.[NOI2011]兔兔与蛋蛋游戏(二分图博弈 匈牙利)

    题目链接 首先空格的移动等价于棋子在黑白格交替移动(设起点移向白格就是黑色),且不会走到到起点距离为奇数的黑格.到起点距离为偶数的白格(删掉就行了),且不会重复走一个格子. (然后策略就同上题了,只不 ...

  6. [模板] 二分图博弈 && BZOJ2463:[中山市选2009]谁能赢呢?

    二分图博弈 from BZOJ 1443 游戏(二分图博弈) - free-loop - 博客园 定义 1.博弈者人数为两人,双方轮流进行决策. 2.博弈状态(对应点)可分为两类(状态空间可分为两个集 ...

  7. BZOJ1443: [JSOI2009]游戏Game

    如果没有不能走的格子的话,和BZOJ2463一样,直接判断是否能二分图匹配 现在有了一些不能走的格子 黑白染色后求出最大匹配 如果是完备匹配,则无论如何后手都能转移到1*2的另一端,故先手必输 否则的 ...

  8. JSOI2009 游戏

    1443: [JSOI2009]游戏Game Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 557  Solved: 251[Submit][Stat ...

  9. 【BZOJ】1443: [JSOI2009]游戏Game

    [算法]博弈论+二分图匹配(最大流) [题解]方格图黑白染色得到二分图, 二分图博弈:当起点不属于某个最大匹配时,后手必胜. 问题转化为那些点不属于某个最大匹配. 先找到一个最大匹配,非匹配点加入答案 ...

随机推荐

  1. VS2010 不显示 最近使用的项目 解决办法

    昨天重装了VS2010,然后开了项目看了下今天早上再打开发现起始页近使用项目列表是空白的,每次打开项目都要去到指定目录去找解决方案才能打开,感觉很麻烦,在网上找了下解决方案,解决步骤下:菜单 —— 运 ...

  2. 属性文件操作之Properties与ResourceBundle

    1.Properties与ResourceBundle 两个类都可以读取属性文件中以key/value形式存储的键值对,ResourceBundle读取属性文件时操作相对简单. 2.Propertie ...

  3. xshell连接虚拟机linux系统失败问题

    问题:在xshell新建对话弹出的对话框中输入ip地址后,确定并没有弹出输入用户名和密码对话框 直接显示连接失败 Could not connect to ): Connection failed. ...

  4. EOJ3134. 短信激活码(大数幂取模)

    题面 输入只有5位,所以转化为long long类型用快速幂取模 前面补0的写法printf("%05lld\n",ans);如果ans不足5位会在前面补0 #include< ...

  5. flask ssti python2和python3 注入总结和区别

    总结一下flask ssti的注入语句 代码 import uuid from flask import Flask, request, make_response, session,render_t ...

  6. TPO-18 C2 Possible participation in a sociology project

    TPO-18 C2 Possible participation in a sociology project 第 1 段 1.listen to a conversation between a s ...

  7. 415. Valid Palindrome【LintCode java】

    Description Given a string, determine if it is a palindrome, considering only alphanumeric character ...

  8. [C++基础] 成员变量的初始化顺序

    转载链接:https://blog.csdn.net/qq_37059483/article/details/78608375 1.成员变量在使用初始化列表初始化时,只与定义成员变量的顺序有关,与构造 ...

  9. 微软职位内部推荐-Senior Software Engineer II-Sharepoint

    微软近期Open的职位: SharePoint is a multi-billion dollar enterprise business that has grown from an on-prem ...

  10. HTML5+Bootstrap 学习笔记 2

    navbar升级 从Bootstrap 2到Bootstrap 3 1. .navbar-inner已从Bootstrap 3中去除. 2. <ul class="nav"& ...