思路:
我们考虑当如果任意一个节点有两个叶子节点 那么Alice选这个点就赢了。
所以现在我们就只剩下每个树枝都是一长链的情况了。
考虑点数n为奇数的情况,每次Alice都选某个叶子的父亲,而Bob则被迫选那个叶子节点。此时无论Bob用不用vip技能,都没用。
考虑n为偶数的情况,Alice每次选某个叶子的父亲,那么Alice一定会输,所以Alice一定要选某个叶子节点,来让Bob染3个点,来达到奇数的局面。而Bob也不傻,当Bob有vip技能时,很明显,Bob每次可以阻断自己来只染两个点,使局面还是偶数。但是我们注意Bob的每次操作其实都是被迫的。所以只要Bob的vip技能不够用了,或者Alice找到了某个点具有两个叶子节点(之前一直在切树),Bob就输了。
ps:
官方题解里有一句话说的好啊:玄不救非,氪不改命。(Bob的技能什么时候发动并没有影响)
#include<stdio.h>
#include <iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#define eps 1e-8
typedef long long int lli;
using namespace std;
int f[555];
int v[555];
int cnt[555];
int main(){
int t,n,k;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
memset(v,0,sizeof(v));
memset(cnt,0,sizeof(cnt));
int temp = 0;
for(int i = 2;i <= n;i++){
scanf("%d",f+i);
v[f[i]]++;//记录父亲节点的孩子个数
if(f[i]==1) temp = i;
}
int flag = 0;
if(v[1]==1){//注意特判,当根节点只有一个孩子的时候,根节点也可能被当成叶子
cnt[temp]++;
}
for(int i = 2;i <= n;i++){
if(!v[i]){
cnt[f[i]]++;
if(cnt[f[i]]>=2){//如果任意一个节点有两个叶子节点 那么A选这个点就赢了
flag = 1;break;
}
}
}
if(flag == 1 || n&1 || ((!(n&1)) && (n/2-1 > k))){
puts("Alice");
}
else{
if(!n&1){
for(int i = 2;i <= n && !flag;i++){//当是偶数且无法逼的bob删成奇数的时候,
int temp = f[i];temp = f[temp]; //判断在删的过程中是否会出现一个节点有两个叶子
while(!v[i] && temp!=1 &&k){
k--;
if(v[temp]>=2){
cnt[temp]++;
if(cnt[temp]==2){flag=1;break;}
}
temp = f[temp];temp = f[temp];
}
}
if(flag == 1)
puts("Alice");
else
puts("Bob");
}
else
puts("Bob");
}
}
return 0;
}