题目大意: 给出一棵树,树上一些节点上有若干个柿子,两个人轮流操作,每次选择一个节点,然后将上面的若干个柿子推到相邻节点上——但是从 x x x 推到 y y y 的柿子不能推回 x x x,或者选择一个离点 k k k 距离为奇数且是叶子的节点,删除上面的若干个柿子,两人都用最优策略,问最后谁能赢?
题解
师兄出的一道题qwq
考虑以点 k k k 为根,那么距离为奇数的点深度就是偶数,然后考虑在深度为偶数的叶子下面再接一个节点,那么删除操作可以转化为将柿子推到这个额外节点上,这样就不存在深度为偶数的叶子了。
然后可以发现,对于深度为奇数的节点,假如一个人将上面的若干个柿子推了一下,那么这些柿子肯定会被推到深度为偶数的节点上,那么另一个人一定可以再推一下这些柿子,然后这些柿子就又回到了深度为奇数的节点上。
也就是说,深度为奇数的节点上的柿子是没用的。
那么,假如将偶数节点上的柿子推到奇数节点上,那么这些柿子就废掉了。
那么这就相当于将深度为偶数的节点上的柿子拿来做 N i m Nim Nim 游戏,那就很简单了。
代码如下:
#include <cstdio>
#include <cstring>
#define maxn 110
int T,n,m,rt,a[maxn],ans;
struct edge{int y,next;}e[maxn<<1];
int first[maxn],len=0;
void buildroad(int x,int y){e[++len]=(edge){y,first[x]};first[x]=len;}
void dfs(int x,int fa,int dep)
{
if(dep%2==0)ans^=a[x];
for(int i=first[x];i;i=e[i].next)
if(e[i].y!=fa)dfs(e[i].y,x,dep+1);
}
int main()
{
scanf("%d",&T);while(T--)
{
scanf("%d %d %d",&n,&m,&rt);
memset(first,0,sizeof(first)),len=ans=0;
for(int i=2,x;i<=n;i++)scanf("%d",&x),buildroad(x,i),buildroad(i,x);
memset(a,0,sizeof(a));
for(int i=1,x,y;i<=m;i++)scanf("%d %d",&x,&y),a[x]=y;
dfs(rt,0,1);if(ans)printf("gg\n");else printf("win\n");
}
}