【题意】:
给定一个以1号节点为根的含N个节点的树,Alice先手,Bob后手玩一个游戏:轮流删去树中的边,之后将与根断开了联系的部分去除。无法继续删边者为负。
【分析】:
这是树的删边博弈游戏,首先先考虑更加简单的链的删边博弈游戏。
链的删边博弈游戏游戏规则:对于一条链,两人轮流删边,脱离根的部分去除,没边可删的人即输。考虑其sg值。
于是乎,很明显,这成了一个Nim游戏的组合。
(上述资料原版来自:【博弈】无向图删边游戏)
【代码】:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 200001
#define MAXN 100001
struct TREENODE{int f,t,next;}a[MAX];
int DATA,N,last[MAXN],tot;
bool vis[MAXN];
void add(int from,int to)
{
a[++tot].t=to;
a[tot].next=last[from];
last[from]=tot;
a[++tot].t=from;
a[tot].next=last[to];
last[to]=tot;
}
int work(int now)
{
int ans=0;
for(int i=last[now];i;i=a[i].next)
{
int to=a[i].t;
if(!vis[to])
{
vis[to]=true;
ans^=(work(to)+1);
}
}
return ans;
}
int main()
{
scanf("%d",&DATA);
for(int data=1;data<=DATA;data++)
{
tot=0;
memset(last,0,sizeof(last));
memset(vis,false,sizeof(vis));
scanf("%d",&N);
for(int i=1;i<N;i++)
{
int F,T;
scanf("%d%d",&F,&T);
add(F,T);
}
vis[1]=true;
if(!work(1)) printf("Bob\n");
else printf("Alice\n");
}
return 0;
}