将其1为根建树,操作显然即去掉一棵子树(非本身)
考虑sg函数,定义$sg(T)$为有根树$T$的sg值,则有以下结论——
结论:令$T'$为$T$的根节点新增一个父亲得到的树,则$sg(T')=sg(T)+1$
假设去掉$T$任意一棵子树(非本身)后会得到$T_{1},T_{2},...,T_{k}$,$T'_{i}$为$T_{i}$的根节点新增一个父亲得到的树,那么$T'$去掉任意一棵子树(非本身)后即会得到$T'_{1},T'_{2},...,T'_{k}$和"一个节点"的树
显然"一个节点"的树的$sg$值为0,因此$sg(T')=mex(\{sg(T'_{i}),0\})$
考虑归纳,并代入$sg(T'_{i})=sg(T_{i})+1$,不难得到$sg(T')=sg(T)+1$,即得证
进一步的,考虑$T$根节点儿子的子树依次为$T_{1},T_{2},...,T_{k}$,显然对$T_{i}$再加上$T$根节点即是一个独立的问题,结合sg函数的性质和结论,也即$sg(T)=\bigoplus_{i=1}^{k}(sg(T_{i})+1)$,再树形dp即可
时间复杂度为$o(n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 vector<int>v[N]; 5 int n,x,y,sg[N]; 6 void dfs(int k,int fa){ 7 for(int i=0;i<v[k].size();i++) 8 if (v[k][i]!=fa){ 9 dfs(v[k][i],k); 10 sg[k]^=sg[v[k][i]]+1; 11 } 12 } 13 int main(){ 14 scanf("%d",&n); 15 for(int i=1;i<n;i++){ 16 scanf("%d%d",&x,&y); 17 v[x].push_back(y); 18 v[y].push_back(x); 19 } 20 dfs(1,0); 21 if (sg[1])printf("Alice\n"); 22 else printf("Bob\n"); 23 return 0; 24 }