原文链接https://www.cnblogs.com/zhouzhendong/p/AGC017D.html
题目传送门 - AGC017D
题意
给定一棵 n 个节点的以节点 1 为根的树。
两个人在博弈,每次可以删除任意一个子树,不能删掉整个树。最终不能操作的人输。
问先手是否必胜。
$nleq 10^5$
题解
考虑处理出每一个节点的 SG 值。
对于节点 x ,显然他的所有子树都是独立的,我们只需要求出所有子树的 SG 值然后异或起来就好了。
假设 y 为 x 的一个儿子,则节点 y 对于 x 的贡献是什么呢?
显然不是 SG[y] ,因为 x 到 y 还有一条边。在 y 子树中操作的任何时候都可以直接删除这条边到达状态 0 ,相当于 y 子树的所有状态都连了一条到 0 的边。
所以 SG'[y] = SG[y] + 1 。
所以 SG[x] 就是所有的 SG'[y] 的异或值(其中 y 为 x 的儿子)。
代码
#include <bits/stdc++.h>
#define y1 __zzd001
using namespace std;
typedef long long LL;
LL read(){
LL x=0;
char ch=getchar();
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
const int N=100005;
int n,sg[N];
vector <int> e[N];
void solve(int x,int pre){
sg[x]=0;
for (auto y : e[x])
if (y!=pre){
solve(y,x);
sg[x]^=sg[y]+1;
}
}
int main(){
n=read();
for (int i=1;i<n;i++){
int x=read(),y=read();
e[x].push_back(y);
e[y].push_back(x);
}
solve(1,0);
puts(sg[1]?"Alice":"Bob");
return 0;
}