2024“钉耙编程”中国大学生算法设计超级联赛(7)1004 战争游戏

Problem Description

坎格鲁斯普雷和袋鼠将军在游玩一款名叫“战争游戏”的游戏,在这款游戏中,坎格鲁斯普雷是进攻方,袋鼠将军是防守方。

游戏的地图可以抽象为一张有着 n 个节点的树。初始时,防守方的人物在 s 号节点。

游戏将会进行 10^{100} 回合,在每一回合中,游戏的流程如下:

首先,进攻方会选择一个节点 p ,作为轰炸中心,并对防守方进行“轰炸预告”,如果在回合结束时防守方所在的节点 t 与轰炸中心 p 的距离不超过轰炸半径 r1​ ,那么防守方的人物将会被炸死,此时游戏结束,进攻方获胜。之后 防守方可以操纵他的人物移动到与当前位置的距离不超过 r2​ 的节点上,然后回合结束。如果防守方的人物在回合结束时没被炸死,那么接着进行下一轮游戏,直到游戏轮次耗尽。若游戏轮次耗尽的时候防守方操纵的人物仍未死亡,那么防守方获胜,游戏结束。

作为袋鼠中的精英,坎格鲁斯普雷和袋鼠将军都是绝顶聪明的(即他们做出的操作都是当前盘面下的最优操作),那么在游戏结束时,谁将获胜?

Input

输入第一行一个整数 T ,表示测试数据组数。 (1≤T≤10^{3})

每组测试数据,第一行四个整数 n , s , r1 , r2 。 (1≤n≤10^{5},1≤s,r1,r2≤n)

之后 (n−1) 行,每行两个整数 ui , vi ,表示一条存在于树内的边。 (1≤ui,vi≤n)

数据保证 ∑n≤2×10^{6}

Output

对于每组测试数据,若坎格鲁斯普雷获胜,输出一行一个字符串 `Kangaroo_Splay` ;否则,输出一行一个字符串 `General_Kangaroo` 。每组测试数据的答案之间需换行。

Sample Input

2
5 3 2 3
1 2
2 3
3 4
3 5
5 1 1 3
1 2
2 3
3 4
3 5

Sample Output

Kangaroo_Splay

General_Kangaroo

思路:想要 General_Kangaroo 赢只有一种情况,就是当 r1*2+1<这棵树的直径(即最长链)并且 r1*2<r2,其他情况都是 Kangaroo_Splay 赢,所以我们只需要用树形dp求这棵树的最大直径即可轻松解决这道题。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
vector<int> G[100005];
int ans[100005];
void dfs(int u,int fa){
    ans[u]=ans[fa]+1;
    for(int i=0;i<G[u].size();i++){
        if(G[u][i]!=fa) dfs(G[u][i],u);
    }
}
signed main()
{
    IOS
    int _;
    cin >> _;
    while(_--){
        int n,s,r1,r2;
        cin >> n >> s >> r1 >> r2;
        for(int i=1;i<=n;i++) G[i].clear();
        for(int i=1;i<n;i++){
            int u,v;
            cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1,0);//跑每个点的深度 
        int idx=1;
        for(int i=1;i<=n;i++){
            if(ans[i]>ans[idx]) idx=i;
        }//idx 是深度最深的叶子节点 
        dfs(idx,0);//跑这棵树的直径(即最长链) 
        int maxn=0;//maxn 记录直径 
        for(int i=1;i<=n;i++){
            maxn=max(maxn,ans[i]);
        }
        if(r1*2+1<maxn && r1*2<r2) cout << "General_Kangaroo" << endl;
        else cout << "Kangaroo_Splay" << endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值