• 【GYM 102832H】【模板】Combination Lock(二分图博弈)


    Combination Lock

    题目链接:GYM 102832H

    题目大意

    给你一个密码锁(至多五位),告诉你一开始的样子,然后两个人轮流选一个位置往上或者往下拧一格。
    然后要使得每次得到的数字之前没有出现过且不是给出的数字。
    要你判断是否先手必胜。

    思路

    麻了写了一天。

    这个是二分图博弈的可以说是模板把,毕竟这个密码锁每次操作必定奇偶变化应该能看出来(我除外)。

    然后就是二分图博弈的样子:
    一个二分图,然后从一个点开始每个人轮流把它按边移动,每次要移动到一个新的位置,无法移动着失败。

    然后先是结论:如果这个图所有最大匹配的方案都包含了起点,那先手必胜,否则后手必胜。

    然后是证明:
    充分性:如果包含起点 S S S,那先手每一步如果跟着匹配边,那后手只能跟着走。因为如果不跟着走,那形成一套 S → p 1 → p 2 → p n S\rightarrow p_1\rightarrow p_2\rightarrow p_n Sp1p2pn,那匹配边就是 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} Sp1,p2p3,...,pn2pn1
    那我们完全可以集体右移: 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} p1p2,p3p4,...,pn1pn,这样长度相同也是最大匹配,但是却不包含了 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 Sp1p2pn,匹配是 p 1 − p 2 , . . . p n − 2 − p n − 1 p_1-p_2,...p_{n-2}-p_{n-1} p1p2,...pn2pn1,你完全可以左右各扩展一下得到 S − p 1 , p 2 − p 3 , . . . , p n − 1 − p n S-p_1,p_2-p_3,...,p_{n-1}-p_n Sp1,p2p3,...,pn1pn,那就不是最大匹配了。

    然后接着考虑如何判断一个点是否一定在最大匹配中。
    其实有一个最直观的办法(也就是我这里用的),就是去掉这个点跑一遍,再加上这个点跑一遍,看两次的最大匹配是否相同。(这里你可以不给之前的边流量重新复制,那你就只需要判第二次是否有流量即可)
    然后还有一种方法就是你可以先跑出一个最大匹配,然后看看是否存在取代边(就是一条匹配边的一个点和一个非匹配的点有连边,那另一个点可以被取代)。
    然后新被取代的又可以去取代别人,然后每个没有被匹配的都这么试一下,就可以得到那些点可以被取代哪些不可以里。

    代码

    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
  • 相关阅读:
    Android Studio新建项目下载依赖慢,只需一个操作解决
    【C++】泛型编程 ⑪ ( 类模板的运算符重载 - 函数实现 写在类外部的不同的 .h 头文件和 .cpp 代码中 )
    .NET 中的反射
    前端进击笔记第十三节 为什么小程序特立独行?
    NEFU算法设计与分析课程设计
    万物皆可“云” 从杭州云栖大会看数智生活的未来
    mysql必知必会
    【C/C++】函数作为参数
    Java--Spring之AOP面向切面编程
    N元语言模型
  • 原文地址:https://blog.csdn.net/weixin_43346722/article/details/125623959