当前位置:网站首页>【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;
}
边栏推荐
- 用列錶初始化你的vector&&initializer_list簡介
- Spire Office 7.5.4 for NET
- Brushless drive design -- on MOS drive circuit
- 14 MySQL-视图
- Rasa 3. X learning series -rasa 3.2.1 new release
- Which side projects can be achieved? Is it difficult for we media to earn more than 10000 a month?
- 【EF Core】EF Core与C# 数据类型映射关系
- Do you regret becoming a programmer?
- STM32__06—单通道ADC
- Research notes I software engineering and calculation volume II (Chapter 1-7)
猜你喜欢

Neural structured learning 4 antagonistic learning for image classification
![[original] what is the core of programmer team management?](/img/11/d4b9929e8aadcaee019f656cb3b9fb.png)
[original] what is the core of programmer team management?

My colleagues quietly told me that flying Book notification can still play like this

Spécifications techniques et lignes directrices pour la sélection des tubes TVS et ESD - Recommandation de jialichuang

芯源&立创EDA训练营——无刷电机驱动

Tips for using pads router

Senparc.Weixin.Sample.MP源码剖析

Live tiktok shop 2022 latest gameplay card slot overseas live e-commerce new traffic

20. Migrate freetype font library

21.PWM应用编程
随机推荐
2022.6.20-6.26 AI industry weekly (issue 103): new little life
2022.6.20-6.26 AI行业周刊(第103期):新的小生命
Hcip course notes-16 VLAN, three-tier architecture, MPLS virtual private line configuration
Initialize your vector & initializer with a list_ List introduction
[classical control theory] summary of automatic control experiment
Spire Office 7.5.4 for NET
21. PWM application programming
无刷驱动设计——浅谈MOS驱动电路
Bao Yan notes II software engineering and calculation volume II (Chapter 13-16)
How to improve eloquence
How to get all the values stored in localstorage
多普勒效应(多普勒频移)
激光slam学习记录
Initialiser votre vecteur & initialisateur avec une liste Introduction à la Liste
Use mapper: --- tkmapper
Qcombox (rewrite) + qcompleter (auto completion, auto loading the drop-down options of qcombox, setting the background color)
el-cascader的使用以及报错解决
C reflection and type
When to use useImperativeHandle, useLayoutEffect, and useDebugValue
98. Verify the binary search tree ●●