codeforces-#668-D

codeforces-#668-D

九月 24, 2020

D. Tree Tag

题意

有两个人A/B在一颗n个点n-1条边的树上

A在a点,B在b点

他们轮流行动,每次行动A可以移动最多da长度的距离

B则最多移动db长度的距离

问A先手能否追到B

题解

A能追到B有且仅有三种情况

  • A第一次就能到达B的位置即 dis A to B<=da

  • A的最大移动距离>=树的直径/2 ,只要A到达树直径的中心点上无论B怎么走都能抓到他

  • 2倍A的最大移动距离>=B的移动距离,B为了和A保持距离

    B会被A逼到角落使B不得不往A的方向跳跃 此时B必定落在A的移动范围内

对于求树的直径 先从任意一点到达它的最远端p 再从p跳到p的最远端p’ 两者距离为树的直径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define Turnoff std::ios::sync_with_stdio(false)
const ll Max=1e5+5;
const ll Mod=998857459;

vector<int>mp[Max];
int Twopoint,fardis,farpoint;
void dfs(int now,int fa,int dis,int to){
if(now==to)Twopoint=dis;
if(dis>fardis){
fardis=dis;
farpoint=now;
}
for(auto i:mp[now]){
if(i==fa)continue;
dfs(i,now,dis+1,to);
}
}
int main() {
Turnoff;
int t;cin>>t;
while(t--){
int n,a,da,b,db;
cin>>n>>a>>b>>da>>db;
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
mp[u].push_back(v);
mp[v].push_back(u);
}
fardis=0,farpoint=a;
dfs(a,0,0,b);
if(Twopoint<=da)cout<<"Alice"<<endl;
else{
//int now=farpoint;
dfs(farpoint,0,0,0);
if(fardis<=2*da||2*da>=db)cout<<"Alice"<<endl;
else cout<<"Bob"<<endl;
}
for(int i=1;i<=n;i++)mp[i].clear();
}
}