HDU 6105 Gameia (博弈)

思路:

我们考虑当如果任意一个节点有两个叶子节点 那么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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值