hdu6105

多校第六場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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章