题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3197
题意:一个森林包含多棵树。游戏者轮流从树上删边,删掉后与树根不相连的就会丢掉。最后不能删的人输。
思路:叶子节点的SG值为0,中间结点的SG值叶子节点的SG值+1的抑或。下面用数学归纳法证明一下。
(1)一个节点和两个节点显然成立。
(2)假设K个节点的树成立。对于K+1个节点。我们首先假设某个节点只有一个子节点,如下图。设根节点为A,中间节点为B。整个树为G,上面的那个子树为G'。那么若在AB边切一刀,则A的SG值为0;若在G'上切一刀,那么其新的SG值可以变为[0,SG[G']-1],所以由结论可得G可以变为[1,SG[G']],然后又可以为0,所以SG[G]=SG[G']+1。
那么如果不是只有一个孩子的?有下图。此时,可以看成是若干子游戏,各个孩子的SG+1的抑或。
const i64 mod=1000000007;
const int MAX=1005;
int n;
vector<int> a[MAX],b;
int DFS(int u,int pre)
{
int i,v,ans=0;
for(i=0;i<SZ(a[u]);i++)
{
v=a[u][i];
if(v==pre) continue;
ans^=(DFS(v,u)+1);
}
return ans;
}
int main()
{
while(scanf("%d",&n)!=-1)
{
int i,x;
for(i=0;i<=n;i++) a[i].clear();
b.clear();
for(i=0;i<n;i++)
{
scanf("%d",&x);
if(x==-1) b.pb(i);
else a[i].pb(x),a[x].pb(i);
}
int ans=0;
for(i=0;i<SZ(b);i++) ans^=DFS(b[i],-1);
if(ans) puts("YES");
else puts("NO");
}
return 0;
}