当前位置:网站首页>【GYM 102832H】【模板】Combination Lock(二分图博弈)
【GYM 102832H】【模板】Combination Lock(二分图博弈)
2022-07-05 23:34:00 【SSL_TJH】
Combination Lock
题目链接:GYM 102832H
题目大意
给你一个密码锁(至多五位),告诉你一开始的样子,然后两个人轮流选一个位置往上或者往下拧一格。
然后要使得每次得到的数字之前没有出现过且不是给出的数字。
要你判断是否先手必胜。
思路
麻了写了一天。
这个是二分图博弈的可以说是模板把,毕竟这个密码锁每次操作必定奇偶变化应该能看出来(我除外)。
然后就是二分图博弈的样子:
一个二分图,然后从一个点开始每个人轮流把它按边移动,每次要移动到一个新的位置,无法移动着失败。
然后先是结论:如果这个图所有最大匹配的方案都包含了起点,那先手必胜,否则后手必胜。
然后是证明:
充分性:如果包含起点 S S S,那先手每一步如果跟着匹配边,那后手只能跟着走。因为如果不跟着走,那形成一套 S → p 1 → p 2 → p n S\rightarrow p_1\rightarrow p_2\rightarrow p_n S→p1→p2→pn,那匹配边就是 S − p 1 , p 2 − p 3 , . . . , p n − 2 − p n − 1 S-p_1,p_2-p_3,...,p_{n-2}-p_{n-1} S−p1,p2−p3,...,pn−2−pn−1。
那我们完全可以集体右移: p 1 − p 2 , p 3 − p 4 , . . . , p n − 1 − p n p_1-p_2,p_3-p_4,...,p_{n-1}-p_{n} p1−p2,p3−p4,...,pn−1−pn,这样长度相同也是最大匹配,但是却不包含了 S S S。
必要性:如果不包含起点 S S S,那对于一个不包含 S S S 的最大匹配。第一步肯定是走在匹配点上(不然这条边是可以放进最大匹配里面的),而后手沿着匹配边一直走的话,先手是走不出的。
因为如果最后一个是非匹配点 S → p 1 → p 2 → p n S\rightarrow p_1\rightarrow p_2\rightarrow p_n S→p1→p2→pn,匹配是 p 1 − p 2 , . . . p n − 2 − p n − 1 p_1-p_2,...p_{n-2}-p_{n-1} p1−p2,...pn−2−pn−1,你完全可以左右各扩展一下得到 S − p 1 , p 2 − p 3 , . . . , p n − 1 − p n S-p_1,p_2-p_3,...,p_{n-1}-p_n S−p1,p2−p3,...,pn−1−pn,那就不是最大匹配了。
然后接着考虑如何判断一个点是否一定在最大匹配中。
其实有一个最直观的办法(也就是我这里用的),就是去掉这个点跑一遍,再加上这个点跑一遍,看两次的最大匹配是否相同。(这里你可以不给之前的边流量重新复制,那你就只需要判第二次是否有流量即可)
然后还有一种方法就是你可以先跑出一个最大匹配,然后看看是否存在取代边(就是一条匹配边的一个点和一个非匹配的点有连边,那另一个点可以被取代)。
然后新被取代的又可以去取代别人,然后每个没有被匹配的都这么试一下,就可以得到那些点可以被取代哪些不可以里。
代码
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 1e5 + 5;
int m, n, ST, M, a[] = {
1, 10, 100, 1000, 10000, 100000}, le[N], KK;
int tot, S, T, deg[N], lee[N];
bool sp[N], odd[N];
queue <int> q;
struct node {
int x, to, nxt, op;
}e[N * 20];
int read() {
int re = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
re = (re << 3) + (re << 1) + c - '0';
c = getchar();
}
return re;
}
void Init() {
KK = 0; for (int i = 0; i < N; i++) le[i] = -1;
memset(sp, 0, sizeof(sp));
}
void link(int x, int y, int z) {
e[++KK] = (node){
z, y, le[x], KK + 1}; le[x] = KK; e[++KK] = (node){
0, x, le[y], KK - 1}; le[y] = KK;
}
void calc(int i) {
for(int j = 0; j < m; j++) {
int bit = i / a[j] % 10, x;
if(bit != 9) x = i + a[j];
else x = i - 9 * a[j];
if (!sp[x]) link(i, x, 1);
if (bit) x = i - a[j];
else x = i + 9 * a[j];
if (!sp[x]) link(i, x, 1);
}
}
bool bfs() {
for (int i = 0; i <= tot; i++) lee[i] = le[i], deg[i] = 0;
q.push(S); deg[S] = 1;
while (!q.empty()) {
int now = q.front(); q.pop();
for (int i = le[now]; ~i; i = e[i].nxt)
if (!deg[e[i].to] && e[i].x) {
deg[e[i].to] = deg[now] + 1;
q.push(e[i].to);
}
}
return deg[T];
}
int dfs(int now, int sum) {
if (now == T) return sum;
int go = 0;
for (int &i = lee[now]; ~i; i = e[i].nxt)
if (deg[e[i].to] == deg[now] + 1 && e[i].x) {
int this_go = dfs(e[i].to, min(e[i].x, sum - go));
if (this_go) {
e[i].x -= this_go; e[e[i].op].x += this_go;
go += this_go; if (go == sum) return go;
}
}
if (go == 0) deg[now] = 0;
return go;
}
int dinic() {
int re = 0; while (bfs()) re += dfs(S, INF); return re;
}
int main() {
for (int i = 0; i < N; i++) {
int id = 0, x = i; while (x) {
id += x % 10; x /= 10;} odd[i] = id & 1;
}
int TT = read();
while (TT--) {
Init();
m = read(); n = read(); ST = read();
M = a[m]; tot = M; S = ++tot; T = ++tot;
for (int i = 1; i <= n; i++) {
int x = read(); sp[x] = 1;
}
for(int i = 0; i < M; i++) {
if(sp[i]) continue;
if(odd[i] == odd[ST]) {
calc(i);
if (i != ST) link(S, i, 1);
}
else {
link(i, T, 1);
}
}
dinic();
link(S, ST, 1);
if (dinic()) printf("Alice\n");
else printf("Bob\n");
}
return 0;
}
边栏推荐
- Rasa 3.x 学习系列-Rasa 3.2.1 新版本发布
- GFS Distributed File System
- XML配置文件(DTD详细讲解)
- C# Linq Demo
- 用列錶初始化你的vector&&initializer_list簡介
- Initialiser votre vecteur & initialisateur avec une liste Introduction à la Liste
- C reflection and type
- 2022.6.20-6.26 AI行业周刊(第103期):新的小生命
- MySQL replace primary key delete primary key add primary key
- el-cascader的使用以及报错解决
猜你喜欢
What if the C disk is not enough? Let's see how I can clean up 25g of temp disk space after I haven't redone the system for 4 years?
JVM details
【LeetCode】5. Valid palindrome
总结了 800多个 Kubectl 别名,再也不怕记不住命令了!
Bao Yan notebook IV software engineering and calculation volume II (Chapter 8-12)
Attacking technology Er - Automation
Open source CRM customer relationship system management system source code, free sharing
18.(arcgis api for js篇)arcgis api for js点采集(SketchViewModel)
《牛客刷verilog》Part III Verilog企业真题
98. Verify the binary search tree ●●
随机推荐
How to get all the values stored in localstorage
Part III Verilog enterprise real topic of "Niuke brush Verilog"
21.PWM应用编程
Qt 一个简单的word文档编辑器
Spire. PDF for NET 8.7.2
Do you regret becoming a programmer?
【SQL】各主流数据库sql拓展语言(T-SQL 、 PL/SQL、PL/PGSQL)
做自媒体影视短视频剪辑号,在哪儿下载素材?
Initialize your vector & initializer with a list_ List introduction
UVA11294-Wedding(2-SAT)
rsync远程同步
TVS管 与 稳压二极管参数对比
98. Verify the binary search tree ●●
Comparison between webgl and webgpu [3] - vertex buffer
QCombox(重写)+QCompleter(自动补全,自动加载qcombox的下拉选项,设置背景颜色)
Research notes I software engineering and calculation volume II (Chapter 1-7)
Hcip course notes-16 VLAN, three-tier architecture, MPLS virtual private line configuration
如何让同步/刷新的图标(el-icon-refresh)旋转起来
GFS分布式文件系统
20. Migrate freetype font library