CF1405D Tree Tag(思维)

思维题,关注一下有哪些输赢关系

1.dis(a,b)<=da,显然,一步就能抓到

2.直径小于2*da,这是本题解题的核心,我们发现alice站在直径的终点就稳赢

3.如果直径大于2*da,我们证明当2*da>=db的时候alice赢,否则bob赢

首先因为我们不在情况2,所以一定可以找到一个点使得这个点与alice相离da+1个位置,并且我们发现如果db>2*da,那么bob永远可以走到这个位置,就是稳赢

如果2*da>=db,alice可以采取策略不断往bob所在子树逼近,因为bob不能跳出掌控的范围,所以bob是必输的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=4e5+10;
const int inf=1e9;
int n;
int dis[N];
int f[N][2];
int h[N],ne[N],e[N],idx;
int res=0;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa){
    int i;
    f[u][0]=f[u][1]=0;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa)
            continue;
        dis[j]=dis[u]+1;
        dfs(j,u);
        if(f[j][0]+1>=f[u][0]){
            f[u][1]=f[u][0];
            f[u][0]=f[j][0]+1;
        }
        else if(f[j][0]+1>f[u][1]){
            f[u][1]=f[j][0]+1;
        }
    }
    res=max(res,f[u][0]+f[u][1]);
}
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        int a,b,da,db;
        cin>>n>>a>>b>>da>>db;
        int i;
        idx=0;
        res=0;
        for(i=1;i<=n;i++){
            h[i]=-1;
            dis[i]=0;
        }
        for(i=1;i<n;i++){
            int x,y;
            cin>>x>>y;
            add(x,y);
            add(y,x);
        }
        dfs(a,-1);
        int flag=0;
        if(da>=dis[b]){
            flag=1;
        }
        if(2*da>=res){
            flag=1;
        }
        if(2*da>=db){
            flag=1;
        }
        if(flag){
            cout<<"Alice"<<endl;
        }
        else{
            cout<<"Bob"<<endl;
        }
    }
    return 0;
}
View Code

 

posted @ 2020-09-28 10:45  朝暮不思  阅读(178)  评论(0)    收藏  举报