多校第六場1010
題目鏈接
題意是有兩個人在玩遊戲,有一棵樹,一開始每個節點都是沒有顏色的,然後A先手,B後手,每次A可以選一個未上色節點塗成白色,B選一個未上色節點塗成黑色,同時與其直接相鄰的點也被塗成黑色(無論已經上色與否),B在遊戲過程中隨時可以做一個小動作就是切割樹的一條邊。當所有點都被上色時,如果節點中有一個是白色的,那麼A獲勝否則B獲勝,問最後勝利的情況。
看起來B好像很吊的樣子,隨時可以切邊,但是實際上分析一下找找規律,發現B要贏其實很難的,不考慮切割時,只有在一棵樹只有兩個點的時候,B才能贏(找規律得出)。當一部分連通塊被染色時,實際上這部分連通塊相當於被切割出去了。
當A對一個點染色的時候,B想要贏必須想辦法把這個點與其周圍某個相鄰點連成的”2-連通塊“分割出去,但是不能隨便分割,因爲有可能導致其它點找不到匹配點。
於是問題就變成了對於樹上任意一點,能否找到一個匹配點,使得被這兩個點被切割後剩下部分仍然能滿足這個性質。我們從葉子節點開始找匹配,就可以解決。同時,要確保B的機會數一定使每次的點對都能被分割出去。其實就是 [K>=n/2-1]
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<iostream>
#include<stdlib.h>
using namespace std;
#define LONG long long
const LONG INF=0x3f3f3f3f;
const LONG MOD=1e9;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
#define lson l , mid , rt<< 1
#define rson mid + 1 ,r , (rt<<1)+1
#define root 1, n , 1
struct Edge{
int to ,next ;
}edge[500];
int fa[500] ;
int head[500] ;
int tot = 0;
int Son[500] ;
int vis[500] ;
void Init()
{
clrI(head) ;
tot = 0 ;
clr0(Son) ;
clr0(vis) ;
}
void Add(int u , int v) {
edge[++tot].to = v ;
edge[tot].next = head [u] ;
head[u] = tot ;
}
int main()
{
int T;
cin >> T;
while(T --)
{
Init() ;
int n ;
int p ;
cin >> n >> p ;
int t ;
for(int i = 2 ;i <= n ; ++ i)
{
scanf("%d" ,&t);
Add(t,i) ;
Son[t] ++;
fa[i] = t ;
}
if(n&1)
{
printf("Alice\n") ;
continue ;
}
if( p < (n/2-1) )
{
printf("Alice\n") ;
continue ;
}
queue <int >que ;
while(!que.empty()) que.pop () ;
int judge = 1;
for(int i = 1;i<=n; ++ i) if(!Son[i])que.push(i) ;
while(!que.empty())
{
int x = que.front() ; que.pop() ;
vis[x] = 1;
if(!vis[fa[x]]) vis[fa[x]] = 1;
else if(vis[fa[x]] || x == 1)
{
judge = 0 ;break ;
}
if(fa[x]!=1)
{
Son[fa[fa[x]]] -- ;
if(!Son[fa[fa[x]]] && !vis[fa[fa[x]]])
que.push(fa[fa[x]]) ;
}
}
for(int i = 1; i<= n ; ++ i)if(!vis[i]){judge = 0;}
if(judge)
printf("Bob\n") ;
else cout<<"Alice"<<endl;
}
}