Description
一棵树,初始时每个节点都没有被染色,
Bob
有
K
次机会在任意时刻一起或单独使用,每次可以切掉一条树边,游戏开始,
Input
第一行一个整数
T
表示用例组数,每组用例首先输入两个整数
Output
输出胜者
Sample Input
2
2 1
1
3 1
1 2
Sample Output
Bob
Alice
Solution
如果 Bob 可以把这棵树分成两两匹配的点对则显然 Bob 获胜,下证其他情况均为 Alice 获胜
一.如果不存在这种两两匹配的方案,那么 Alice 每次从叶子节点开始染叶子节点的父亲节点,那么 Bob 就只能染叶子节点,否则下一步 Alice 染叶子 Bob 无法将该叶子节点变成黑色, Bob 的操作失去意义,因为就算 Bob 删边,由于不存在两两匹配的方案,最终必然是 Bob 用完删边的机会被 Alice 染到一个周围都被染色的孤立点进而获胜
二.如果存在两两匹配的方案但是 Bob 的操作不能把这棵树分成两两匹配的点对,每次 Alice 染一个没有兄弟的叶子节点,那么 Bob 就必须染这个点的父亲节点,但是由于染父亲节点会让父亲节点的父亲节点也变成黑色,没染色的节点数变成奇数,由第一种情况知 Bob 失败,故 Bob 被迫把父亲节点与其父亲节点之间的边删掉使得该叶子节点与其父亲节点孤立出来形成一个点对,重复此过程最终会有两种情况:
1.所有叶子节点均有兄弟节点, Alice 染这个叶子节点的父亲节点,那么 Bob 为使该点变成黑色就会染该点的父亲节点或该点的儿子节点,但是总会多出孤立的叶子节点, Alice 获胜
2. Bob 删边次数用光, Bob 被迫染色形成一个奇数节点的子树,由第一种情况知 Alice 获胜
综上,只有当这棵树可以被分成两两匹配的点对且 K≥n2−1 时 Bob 获胜,判断该棵树是否可以分成两两匹配的点对只需要从叶子节点贪心的匹配即可,一遍树形DP即可解决
Code
#include<cstdio>
#include<algorithm>
using namespace std;
namespace fastIO
{
#define BUF_SIZE 1000
//fread -> read
bool IOerror=0;
inline char nc()
{
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if(p1==pend)
{
p1=buf;
pend=buf+fread(buf,1,BUF_SIZE,stdin);
if(pend==p1)
{
IOerror=1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch)
{
return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}
inline void read(int &x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');
}
inline void readc(char &x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
x=ch;
}
#undef BUF_SIZE
};
using namespace fastIO;
const int maxn=501;
struct node
{
int v,next;
}e[maxn];
int head[maxn],tot;
int T,n,k,fa[maxn];
void add(int u,int v)
{
e[tot].v=v,e[tot].next=head[u],head[u]=tot++;
}
int dfs(int u)
{
int num=0;
for(int i=head[u];~i;i=e[i].next)
{
int t=dfs(e[i].v);
if(t==-1)return -1;
if(t==1)num++;
if(num>1)return -1;//有多个还没匹配的儿子则Alice赢
}
if(num==0)return 1;//所有儿子全部匹配,该点未匹配
return 0;//该点与某个儿子匹配
}
int main()
{
read(T);
while(T--)
{
read(n),read(k);
for(int i=2;i<=n;i++)read(fa[i]);
int flag=1;
if(n%2==0&&k>=n/2-1)
{
tot=0;
for(int i=1;i<=n;i++)head[i]=-1;
for(int i=2;i<=n;i++)add(fa[i],i);
if(dfs(1)!=-1)flag=0;
}
printf("%s\n",flag?"Alice":"Bob");
}
return 0;
}