当前位置:网站首页>【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;
}
边栏推荐
猜你喜欢
Comparison of parameters between TVs tube and zener diode
保研笔记二 软件工程与计算卷二(13-16章)
Rasa 3. X learning series -rasa x Community Edition (Free Edition) changes
GFS分布式文件系統
Spire Office 7.5.4 for NET
STM32__ 06 - single channel ADC
Spire Office 7.5.4 for NET
Laser slam learning record
保研笔记四 软件工程与计算卷二(8-12章)
4点告诉你实时聊天与聊天机器人组合的优势
随机推荐
如何让同步/刷新的图标(el-icon-refresh)旋转起来
芯源&立创EDA训练营——无刷电机驱动
[EF core] mapping relationship between EF core and C data type
2022.6.20-6.26 AI industry weekly (issue 103): new little life
Différence entre hors bande et en bande
Go language introduction detailed tutorial (I): go language in the era
Part III Verilog enterprise real topic of "Niuke brush Verilog"
C reflection and type
Common static methods of math class
Neural structured learning - Part 3: training with synthesized graphs
Golang code checking tool
Attacking technology Er - Automation
How to enable relationship view in phpMyAdmin - how to enable relationship view in phpMyAdmin
11gR2 Database Services for &quot;Policy&quot; and &quot;Administrator&quot; Managed Databases (文件 I
What is a humble but profitable sideline?
Rethinking about MySQL query optimization
激光slam学习记录
2022.6.20-6.26 AI行业周刊(第103期):新的小生命
Bao Yan notebook IV software engineering and calculation volume II (Chapter 8-12)
CloudCompare&PCL 点云随机添加噪声