1.题目
传送门:Tree Tag - 洛谷
2.思路
我们考虑什么情况下Alice可以获胜.
如果 ≤ da,则Alice可以一步就追上Bob.
如果Alice处在一个能覆盖整棵树的点,即2da + 1≥树的直径,那么Bob也无论走到哪里Alice都能追到,Alice获胜.
其它情况下,Alice会一步一步逼近Bob,并一定能把Bob逼近某棵子树.
如果当前Alice占据一个点,使Bob无论怎么走都还在Alice的控制范围内,那么Alice必胜.
此时条件即为2da≥db.
最后一种情况有些同学可能没听懂,我来举个栗子
那么此时如果 是Bob走,并且满足2da≥db的话
如果Bob继续往下走,Alice肯定能继续追(其实Bob只能往下走,不然一步就会被追上),而当Bob走到一个子节点,没办法往下走的时候,那么他就必输
除以上条件外,Bob获胜,因为他可以再Alice靠近他的时候不断反向跳走.
总结一下:
只有三种情况 Alice 赢
- dis(a,b)≤da
- 2×da≥db 此时只要一步步逼近即可
- 树的直径 ≤2×da 此时只要占据直径中点即可
3.代码
#include <bits/stdc++.h>
using namespace std;
int t,n,a,u,v,b,da,db,deep[1000001],deep_2[1000001],zj,zjj,lzj;
vector<int> vec[1000001];
void dfs(int x,int fa,int d)
{
deep[x] = d;
for(int i = 0;i < vec[x].size();i++)
if(vec[x][i] != fa)
dfs(vec[x][i],x,d + 1);
}
void qzj()//求树的直径
{
dfs(1,0,0);
int t = 0;
for(int i = 1;i <= n;i++)
if(t < deep[i])
{
t = deep[i];
zj = i;
}
dfs(zj,0,0);
t = 0;
for(int i = 1;i <= n;i++)
if(t < deep[i])
{
t = deep[i];
zjj = i;
}
lzj = t;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>a>>b>>da>>db;
for(int i = 1; i <= n; i++) vec[i].clear();
for(int i = 1;i < n;i++)
{
cin>>u>>v;
vec[u].push_back(v);
vec[v].push_back(u);
}
if(2 * da >= db)
{
cout<<"Alice\n";
continue;
}
qzj();
if(2 * da >= lzj)
{
cout<<"Alice\n";
continue;
}
dfs(a,0,0);
if(deep[b] <= da)
{
cout<<"Alice\n";
continue;
}
cout<<"Bob\n";
}
return 0;
}
4.结语
如果对您有帮助的话,记得点个赞支持一下QwQ疯狂明示