题目链接:hdu 5996 dingyeye loves stone
题意:
给你一棵树,树的每一个节点有a[i]个石子,每个人可以将这个节点的石子移向它的父亲,如果没有合法操作,那么就算输,现在给你当前的局面,问你能否赢
题解:
设根节点的深度为0,将所有深度为奇数的节点的石子数目xor起来,则先手必胜当且仅当这个xor和不为0。 证明同阶梯博弈。对于偶深度的点上的石子,若对手移动它们,则可模仿操作;对于奇深度上的石子,移动一次即进入偶深度的点。 时空复杂度O(n)。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 const int N=1e5+7; 6 vector<int>G[N]; 7 int a[N],ans,t,n,x; 8 9 void dfs(int u=0,int fa=0,int cnt=1) 10 { 11 int en=G[u].size()-1; 12 F(i,0,en)if(G[u][i]!=fa) 13 { 14 if(cnt&1)ans^=a[G[u][i]]; 15 dfs(G[u][i],u,cnt+1); 16 } 17 } 18 19 int main(){ 20 scanf("%d",&t); 21 while(t--) 22 { 23 scanf("%d",&n); 24 F(i,0,n)G[i].clear(); 25 F(i,1,n-1) 26 { 27 scanf("%d",&x); 28 G[x].push_back(i); 29 G[i].push_back(x); 30 } 31 F(i,1,n)scanf("%d",a+i-1); 32 ans=0,dfs(); 33 if(ans==0)puts("lose"); 34 else puts("win"); 35 } 36 return 0; 37 }