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;
}