bzoj 2437 [Noi2011]兔兔与蛋蛋 [二分图匹配]
来源:互联网 发布:淘宝网一件代发可信吗 编辑:程序博客网 时间:2024/05/01 19:51
描述
这些天,兔兔和蛋蛋喜欢上了一种新的棋类游戏。这个游戏是在一个 n 行 m 列的棋盘上进行的。游戏开始之前,棋盘上有一个格子是空的,其它的格子中都放置了一枚棋子,棋子或者是黑色,或者是白色。每一局游戏总是兔兔先操作,之后双方轮流操作,具体操作为:兔兔每次操作时,选择一枚与空格相邻的白色棋子,将它移进空格。蛋蛋每次操作时,选择一枚与空格相邻的黑色棋子,将它移进空格。第一个不能按照规则操作的人输掉游戏。
最近兔兔总是输掉游戏,而且蛋蛋格外嚣张,于是兔兔想请她的好朋友——你——来帮助她。她带来了一局输给蛋蛋的游戏的实录,请你指出这一局游戏中所有她“犯错误”的地方。注意:两个格子相邻当且仅当它们有一条公共边。兔兔的操作是“犯错误”的,当且仅当,在这次操作前兔兔有必胜策略,而这次操作后蛋蛋有必胜策略。
格式
输入格式
输入的第一行包含两个正整数 n、m。接下来 n行描述初始棋盘。其中第i 行包含 m个字符,每个字符都是大写英文字母"X"、大写英文字母"O"或点号"."之一,分别表示对应的棋盘格中有黑色棋子、有白色棋子和没有棋子。其中点号"."恰好出现一次。接下来一行包含一个整数 k(1≤k≤1000) ,表示兔兔和蛋蛋各进行了k次操作。接下来 2k行描述一局游戏的过程。其中第 2i – 1行是兔兔的第 i 次操作(编号为i的操作) ,第2i行是蛋蛋的第i次操作。每个操作使用两个整数x,y来描述,表示将第x行第y列中的棋子移进空格中。输入保证整个棋盘中只有一个格子没有棋子, 游戏过程中兔兔和蛋蛋的每个操作都是合法的,且最后蛋蛋获胜。
输出格式
输出文件的第一行包含一个整数r,表示兔兔犯错误的总次数。接下来r 行按递增的顺序给出兔兔“犯错误”的操作编号。其中第 i 行包含一个整数ai表示兔兔第i 个犯错误的操作是他在游戏中的第 ai次操作。
样例1
样例输入1
1 6 XO.OXO 1 1 2 1 1
样例输出1
1 1
样例2
样例输入2
3 3 XOX O.O XOX 4 2 3 1 3 1 2 1 1 2 1 3 1 3 2 3 3
样例输出2
0
样例3
样例输入3
4 4 OOXX OXXO OO.O XXXO 2 3 2 2 2 1 2 1 3
样例输出3
2 1 2
提示
1~2: n=1, 1<=m<=203: n=3, m=44~5: n=4, m=46~7: n=4, m=58: n=3, m=79~14: n=2, 1<=m<=4015~16: 1<=n<=16, 1<=m<=1617~20: 1<=n<=40, 1<=m<=40
Solution
可以看做是将空格按照黑白交替的方式移动。
先把格子黑白染色,不妨令起点为黑色,相邻且颜色不同的格子连边。连边时注意,假设起点坐标为
如果起点在一定
最大匹配中,则一定先手必胜。因为起点一定在奇数边的交错轨中,只要每次都沿着匹配的边走,一定可以赢。
如果起点不一定
在最大匹配中,则后手必胜。因为第一步走到的点,一定在不包括起点的最大匹配中。
所以只要当前点一定
在最大匹配中就是必胜态,如果走之前是必胜态,走之后还是必胜态,那么说明这一步就走错了。
#include <bits/stdc++.h>using namespace std;int n, m;int arr[45][45];int tot;int x, y;int num[45][45];vector<int> edges[10005];bool vis[10005], ban[10005];int mat[10050];bool dfs(int i) { if (ban[i]) return false; for (int j = 0; j < edges[i].size(); j++) { int k = edges[i][j]; if (!vis[k] && !ban[k]) { vis[k] = 1; if (!mat[k] || dfs(mat[k])) { mat[k] = i; mat[i] = k; return true; } } } return false;}int ans[10005];int main() { scanf("%d %d", &n, &m); char str[45]; for (int i = 1; i <= n; i++) { scanf("%s", str + 1); for (int j = 1; j <= m; j++) { if (str[j] == 'O') arr[i][j] = 1; else if (str[j] == 'X') arr[i][j] = 2; else arr[i][j] = 2, x = i, y = j; } } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (arr[i][j] == 1 ^ (((i + j) & 1) == ((x + y) & 1))) num[i][j] = ++tot; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (!num[i][j]) continue; if (num[i + 1][j]) { edges[num[i][j]].push_back(num[i + 1][j]); edges[num[i + 1][j]].push_back(num[i][j]); } if (num[i][j + 1]) { edges[num[i][j]].push_back(num[i][j + 1]); edges[num[i][j + 1]].push_back(num[i][j]); } } } for (int i = 1; i <= tot; i++) { memset(vis, 0, sizeof(vis)); if (!mat[i]) dfs(i); } int k; scanf("%d", &k); for (int i = 1; i <= k << 1; i++) { int fuck = num[x][y]; ban[fuck] = 1; if (mat[fuck]) { int match = mat[fuck]; mat[match] = mat[fuck] = 0; memset(vis, 0, sizeof(vis)); ans[i] = (!dfs(match)); } scanf("%d %d", &x, &y); } int res = 0; for (int i = 1; i <= k; i++) res += (ans[i * 2 - 1] & ans[i * 2]); printf("%d\n", res); for (int i = 1; i <= k; i++) { if (ans[i * 2 - 1] & ans[i * 2]) { printf("%d\n", i); } } return 0;}
0 0
- bzoj 2437 [Noi2011]兔兔与蛋蛋 [二分图匹配]
- [BZOJ]2437 [NOI2011] 兔兔与蛋蛋 二分图博弈
- [BZOJ]2437: [Noi2011]兔兔与蛋蛋 二分图匹配+博弈
- 【博弈+二分图匹配】[NOI2011]兔兔与蛋蛋游戏
- [二分图博弈] BZOJ 1443 [JSOI2009]游戏Game & BZOJ 2437 [Noi2011]兔兔与蛋蛋
- bzoj 2437: [Noi2011]兔兔与蛋蛋 (二分图博弈+dinic)
- 【bzoj2437】【NOI2011】【兔兔与蛋蛋】【二分图博弈】
- bzoj2437: [Noi2011]兔兔与蛋蛋 二分图博弈
- [BZOJ 2437][NOI 2011]兔兔与蛋蛋(二分图匹配)
- BZOJ 2437 兔兔与蛋蛋 (博弈论 二分图匹配)
- ★【二分图匹配】【博弈论】【NOI2011】兔兔和蛋蛋的游戏
- bzoj2437 [Noi2011]兔兔与蛋蛋
- BZOJ2437: [Noi2011]兔兔与蛋蛋
- 【BZOJ2437】【codevs1949】兔兔与蛋蛋游戏,博弈+二分图匹配
- 【NOI2011T6】兔兔与蛋蛋的游戏-二分图最大匹配+博弈
- 【二分图匹配复习】 noi2011 game
- NOI 兔兔与蛋蛋的游戏
- BZOJ 1059 二分图匹配
- HTTP详解(1)-工作原理
- Deep learning:四十一(Dropout简单理解)
- 【Android】 R.layout.main报错问题
- NIO简介
- iTest--记录android app消耗的cpu/内存/流量 /电量
- bzoj 2437 [Noi2011]兔兔与蛋蛋 [二分图匹配]
- multisim 10.0安装、破解、汉化
- salesforce 分页
- 微信开发 BAE运平台和java语音,微信mysql数据库开发实例 --图文开发教程
- powerpc 设备树dts 详解
- 安卓4.4限制外置SD卡写入权限的破解方法
- probit logit
- spark:SparkSQL应用--46
- Program Pack