1. 程式人生 > 實用技巧 >【D. Tree Tag】

【D. Tree Tag】

D. Tree Tag

題意:

\(a\)\(b\) 在樹上, 每次最多移動的距離為 \(da\) , \(db\)\(a\) 先行動,問能否在有限次內追上 \(b\)

打比賽的時候以為是固定距離 \(da\) , \(db\)

...

其實想起來也很簡單

  • 若第一步能抓到, \(a\) 贏了
  • \(2da \ge Tree \ Diameter\) (樹的直徑),\(a\)
  • $2da < db $ , \(b\) 贏了
  • \(2da \ge db\)\(a\) 贏了

$2da < db $ , \(b\) 贏了

因為 \(b\) 可以一直不動,直到 \(dis(a,b) \le da\)

,此時 \(b\) 可以跳出 \(a\) 的範圍

求出樹的直徑就可以

  1. 先dfs一遍,找出最遠的點,在dfs這個最遠的點。兩遍dfs
  2. 直接dfs
#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+10;
vector<int>adj[maxn];

int dep[maxn];
int d;
int dfs(int u,int pre){
    int maxpath = 0;

    for(int v : adj[u]){
        if(v == pre)continue;
        dep[v] = dep[u] + 1;
        int nowpath = 1 + dfs(v,u);
        d = max(d,nowpath + maxpath);
        maxpath = max(maxpath,nowpath);
    }

    return maxpath;
}

int a,b,da,db,n;

int main(){
    ios_base::sync_with_stdio(0); //ios_base是父類
    //ios::sync_with_stdio(0);
    int t;
    cin >> t;
    while(t--){
        cin >> n >> a >> b >> da >> db;

        for(int i = 1;i <= n;i++)adj[i].clear();

        for(int i = 0;i < n - 1;i++){
            int u,v;cin >> u >> v;
            adj[u].push_back(v);
            adj[v].push_back(u);
        }

        d = 0;
        dep[a] = 0;
        dfs(a,-1);

        cout << (2*da>=min(d,db) || dep[b] <= da ? "Alice" : "Bob") << endl;
    }
}

這個 \(dfs\) 妙wa