有一棵 (N) 个节点的树,节点标号为 (1,2,⋯,N),边用 ((x_i,y_i))表示。 Alice 和 Bob 在这棵树上玩一个游戏,Alice先手,两人轮流操作:
选择一条树上存在的边,把它断开使树变成两个连通块。然后把不包含 (1) 号点的联通块删除
当一个玩家不能操作时输,你需要算出:假如两人都按最优策略操作,谁将获胜。
[sg(u)=igoplus_{vin son(u)}sg(v)+1
]
证明还不会,占个坑,好像还有个叫克朗原理的东西,有空学学
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
const int N = 2e5;
using namespace std;
int n,edge[N * 2 + 5],nxt[N * 2 + 5],head[N + 5],edge_cnt,sg[N + 5];
void add_edge(int u,int v)
{
edge[++edge_cnt] = v;
nxt[edge_cnt] = head[u];
head[u] = edge_cnt;
}
void dfs(int u,int fa)
{
for (int i = head[u];i;i = nxt[i])
{
int v = edge[i];
if (v == fa)
continue;
dfs(v,u);
sg[u] ^= sg[v] + 1;
}
}
int main()
{
scanf("%d",&n);
int u,v;
for (int i = 1;i < n;i++)
{
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(1,0);
if (sg[1])
cout<<"Alice"<<endl;
else
cout<<"Bob"<<endl;
return 0;
}