标签:博弈 print for push auto 无法 += vector 接下来
给一棵树,先手可以任意选一个点染色,接下来每个人可以将当前点的一个祖先或一个孩子染色,一个点只能被染色一次,谁无点可以染色谁就输了。
对于一个点,可以到达的点有所有祖先和所有孩子。如果u可以到达v节点,那么v节点显然也可以到达u节点。
此时我们可以考虑将树上博弈转化成图。n个节点,每个点与可到达的节点连边,就会形成一张图。
手玩几个例子,大概可以发现当最大匹配是完美匹配的时候后手必胜,否则先手必胜。下面给出证明。
因为完美匹配,所以n个点必可以分成n/2组,\((v_1,v_2),(v_3,v_4)...(v_{n-1},v_n)\),那么先手每选一个点,后手就选与之同组的一个点。那么先手必将在某一步无路可走。后手必胜。
设最大匹配\(E={(v_1,v_2),(v_3,v_4)...(v_{k-1},v_k)}\)。那么先手选一个不在匹配内的点,会发生以下两种情况:
(1)后手选择匹配内的点。
此时先手如同1进行操作就可以必胜。因为如果后手在某一轮选择一个匹配外的点,例如在\(v_4\)后选择一个匹配外的点,我们就会发现\((v_a,v_1),(v_2,v_3)(v_4,v_b)\)是可达的,那么\({(v_a,v_1),(v_2,v_3)(v_4,v_b)...(v_{k-1},v_k)}\)就是一个更大的匹配,与假设不符。所以后手无法再次选择匹配外的点,游戏如1进行,先手此时必胜。
(2)后手也选择匹配外的点。
那么很显然,\((v_a,v_b)\)是可达的,可以加入最大匹配,与假设不符。不可能。
所以,最大匹配不是完美匹配时,先手必胜。
于是,题目就转换成了求由这棵树构成的图是否具有完美匹配。树DP即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
int f[maxn + 11];
vector <int> edge[maxn + 11];
void dfs(int x,int fa) {
for (auto v : edge[x]) {
if (v == fa) continue;
dfs(v , x);
f[x] += f[v];
}
if (f[x]) f[x] -= 1;
else f[x] = 1;
}
int main(){
int n;
scanf("%d",&n);
for (int i = 1; i < n; i++) {
int u,v;
scanf("%d %d",&u,&v);
edge[u].push_back(v);
edge[v].push_back(u);
}
dfs(1 , 0);
if (!f[1]) printf("Bob\n"); else printf("Alice\n");
}
标签:博弈 print for push auto 无法 += vector 接下来
原文地址:https://www.cnblogs.com/Embiid/p/12617850.html