BZOJ

题意:

给出一个\(n*m\)的网格,其中有一些障碍点。

现在两个人玩游戏,首先先手选定一个点,然后从后手开始轮流移动,不能移动者即输掉这次游戏。

规定不能移动到那些之前已经到过的格子上。

思路:

  • 网格图可以联想到二分图,我们可以对其进行黑白染色。
  • 注意如果先手必赢的话,直到终点只会走偶数步,也就是说起点和终点格子的颜色不变。
  • 也就是说,如果从二分图的左边出发的话,也只能到左边。这种情况等价于从二分图最大匹配中的非匹配点出发,也一定最后到达的左边。
  • 因为最大匹配的情况可能有多种,所有可能的非匹配点都是答案。模拟一下,发现从左边的一个非匹配点出发,到达的所有的左边的点都是答案。因为如果到达的是非匹配点,那么显然;如果到达的是匹配点,那么可以通过交换边使得这个点变为非匹配点。

在右侧的情况同理。实现的话用网络流会快很多,并且直接从源汇点出发dfs即可。

代码如下:

/*
* Author: heyuhhh
* Created Time: 2019/11/6 21:34:15
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 105; int n, m;
int col[N * N];
char s[N];
int mp[N][N], tot; #define _S heyuhhh
template <class T>
struct Dinic{
struct Edge{
int v, next;
T flow;
Edge(){}
Edge(int v, int next, T flow) : v(v), next(next), flow(flow) {}
}e[500005];
int head[N * N], tot;
int dep[N * N];
void init() {
memset(head, -1, sizeof(head)); tot = 0;
}
void adde(int u, int v, T w, T rw = 0) {
e[tot] = Edge(v, head[u], w);
head[u] = tot++;
e[tot] = Edge(u, head[v], rw);
head[v] = tot++;
}
bool BFS(int _S, int _T) {
memset(dep, 0, sizeof(dep));
queue <int> q; q.push(_S); dep[_S] = 1;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(!dep[v] && e[i].flow > 0) {
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[_T] != 0;
}
T dfs(int _S, int _T, T a) {
T flow = 0, f;
if(_S == _T || a == 0) return a;
for(int i = head[_S]; ~i; i = e[i].next) {
int v = e[i].v;
if(dep[v] != dep[_S] + 1) continue;
f = dfs(v, _T, min(a, e[i].flow));
if(f) {
e[i].flow -= f;
e[i ^ 1].flow += f;
flow += f;
a -= f;
if(a == 0) break;
}
}
if(!flow) dep[_S] = -1;
return flow;
}
T dinic(int _S, int _T) {
T max_flow = 0;
while(BFS(_S, _T)) max_flow += dfs(_S, _T, INF);
return max_flow;
}
bool chk[N * N], vis[N * N];
int ans;
void go(int u, int d) {
vis[u] = 1;
if(u >= 1 && u <= tot) {
if(col[u] == d) ++ans, chk[u] = 1;
}
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if(!vis[v] && e[i ^ (1 - d)].flow > 0) go(v, d);
}
}
void print() {
if(ans) cout << "WIN" << '\n';
else cout << "LOSE" << '\n';
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(mp[i][j] && chk[mp[i][j]]) cout << i << ' ' << j << '\n';
}
}
}
}; Dinic <int> solver; const int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, 1, -1};
bool ok(int x, int y) {
return x >= 1 && y >= 1 && x <= n && y <= m && mp[x][y] && (x + y) % 2 == 0;
}
void run() {
solver.init();
cin >> n >> m;
for(int i = 1; i <= n; i++) {
cin >> (s + 1);
for(int j = 1; j <= m; j++) {
if(s[j] == '.') mp[i][j] = ++tot;
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(i + j & 1 && mp[i][j]) {
for(int k = 0; k < 4; k++) {
int nx = i + dx[k], ny = j + dy[k];
if(ok(nx, ny)) solver.adde(mp[i][j], mp[nx][ny], 1);
}
}
}
}
int S = 0, T = tot + 1;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) if(mp[i][j]) {
if(i + j & 1) solver.adde(S, mp[i][j], 1), col[mp[i][j]] = 1;
else solver.adde(mp[i][j], T, 1);
}
}
solver.dinic(S, T);
solver.go(S, 1); solver.go(T, 0);
solver.print();
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}

【BZOJ1443】[JSOI2009]游戏Game(二分图+博弈)的更多相关文章

  1. BZOJ.1443.[JSOI2009]游戏Game(二分图博弈 匈牙利)

    题目链接 \(Description\) 一个\(N*M\)的有障碍的棋盘,先手放置棋子后,从后手开始轮流移动棋子,不能走重复的位置,不能移动的输.求在哪些位置放棋子是先手必胜的. \(Solutio ...

  2. 【BZOJ1443】游戏(二分图匹配,博弈论)

    [BZOJ1443]游戏(二分图匹配,博弈论) 题面 BZOJ 题解 很明显的二分图博弈问题. 发现每次移动一定是从一个黑点到达一个白点,或者反过来. 所以可以对于棋盘进行染色然后连边. 考虑一下必胜 ...

  3. BZOJ1443: [JSOI2009]游戏Game

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

  4. BZOJ1443 [JSOI2009]游戏Game 【博弈论 + 二分图匹配】

    题目链接 BZOJ1443 题解 既然是网格图,便可以二分染色 二分染色后发现,游戏路径是黑白交错的 让人想到匹配时的增广路 后手要赢[指移动的后手],必须在一个与起点同色的地方终止 容易想到完全匹配 ...

  5. [JSOI2009]游戏 二分图博弈

    题面 题面 题解 二分图博弈的模板题,只要会二分图博弈就可以做了,可以当做板子打. 根据二分图博弈,如果一个点x在某种方案中不属于最大匹配,那么这是一个先手必败点. 因为对方先手,因此我们就是要找这样 ...

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

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

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

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

  8. JSOI2009 游戏

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

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

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

  10. 【BZOJ4554】游戏(二分图匹配,网络流)

    [BZOJ4554]游戏(二分图匹配,网络流) 题解 Description 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若干个炸弹,看 是否能炸到对手, ...

随机推荐

  1. MySQL 数据库查询数据,过滤重复数据保留一条数据---(MySQL中的row_number变相实现方法)

    转自: http://www.maomao365.com/?p=10564 摘要: 下文讲述MySQL数据库查询重复数据时,只保留一条数据的方法 实现思路: 在MySQL数据库中没有row_numbe ...

  2. Makefile 文件格式;makefile伪目标

    Makefile包含 目标文件.依赖文件.可运行命令三部分. 每部分的基本格式例如以下: test: prog.o  code.o gcc  -o  test   prog.o   code.o 当中 ...

  3. Linux—系统管理

    查看Linux系统版本                                                                    CentOS系统 # centos7查看命 ...

  4. android 圆角ImageView类,可设置弧度

    public class RoundImageView extends ImageView { private Paint paint; private int roundWidth = 50; pr ...

  5. git pull出错:cannot pull into a repository with state: merging_resolved"

    git pull 出错解放办法:1.尝试先提交现有代码到本地,再更新2.git reset —hard

  6. 解决SQL Server中无管理员账户权限问题

    遇到忘记SQL Server管理员账户密码或管理员账户被意外删除的情况,如何在SQL Server中添加一个新的管理员账户?按一下步骤操作可添加一个windows账户到SQL Server中,并分配数 ...

  7. vue表格合并行的一个实例

        一.element控件实现 在平常的应用中,需要用到合并单元格的操作,在Excel中,这种操作很好实现,但在实际项目中,常常需要借助element控件来实现. 下面是element中的一个实例 ...

  8. Ubuntu sudo 免密码

    sudo visudo 这里默认打开的是 nano 编辑器,不习惯可以把默认编辑器换成 vim, 参考 Ubuntu 修改默认编辑器 test ALL=NOPASSWD: ALL

  9. Python爬虫教程-使用chardet

    Spider-03-使用chardet继续学习python爬虫,我们经常出现解码问题,因为所有的页面编码都不统一,我们使用chardet检测页面的编码,尽可能的减少编码问题的出现 网页编码问题解决使用 ...

  10. 打开Github网站反应慢的问题

    解决办法: 为了提高速度,可以使用HOSTS加速对Github网站加载的资源网站域名解析. 具体做法: 修改  C:\Windows\System32\drivers\etc  中的hosts文件(P ...