【AtCoder Grand Contest 017 D】Game on Tree

博弈论。

题目大意:

给定一棵树,以 $1$ 为根。双方轮流操作,每次选定一条边断掉,并扔掉和 $1$ 不在一个连通块里的点和边。不能操作者输。

问先手是否有必胜策略。

题解:

一棵树上面再加一个结点,一条边,其 sg 值加一。

一棵树的 sg 值是其所有子树 sg 值加一后的 xor 和。

推出整棵树的 sg 值即可。

Code:

#include<cstdio>
const int N=2e5+5;
struct edge{
    int to,nxt;
}e[N<<1];
int head[N],n,cnt;
int g(int u,int p){
    int r=0;
    for(int i=head[u];i;i=e[i].nxt)
    if(e[i].to!=p)r^=g(e[i].to,u)+1;
    return r;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        e[++cnt]=(edge){v,head[u]},head[u]=cnt;
        e[++cnt]=(edge){u,head[v]},head[v]=cnt;
    }
    puts(g(1,0)?"Alice":"Bob");
    return 0;
}