【Codeforces Round #668 (Div. 2) D】Tree Tag

题目链接

点我呀

翻译

给你一棵树,一个人((Alice))在 (a) 处,一个人((Bob))在 (b) 处,其中 (a) 每次可以移动到距离(经过的边的个数)为 (da) 以内的任意一个点上,(b) 每次可以移动到距离为 (db) 以内的任意一个点上。

(a) 上的人 (Alice) 先移动,问 (A) 能否在有限次的移动过后和 (Bob) 在同一个节点上,如果能够做到, 那么 (A) 赢,否则 (B) 赢。(A)(B) 都会采取有利于自己的最佳策略。

问你最后谁会赢。

题解

我们分成 (4) 类情况讨论:

  • (dis(a,b)le da), 那么显然 (Alice) 只需走一次,就能直接抓到 (Bob), 因此 (Alice) 赢。
  • (2 imes dage diameter(T)), 其中 (diameter(T)) 表示树的直径。这种情况下, 只要 (Alice) 走到树的直径的中点上,那么下一次轮到 (Alice) 走的时候,她就可以走到树上的任意一个位置了,(Bob)也就无处藏身了,因此 (Alice) 赢。
  • (db > 2 imes da), 因为已经排除了第一种情况,所以我们可以保证 (Bob) 能至少移动那么一次。我们可以采取这样的策略: 在 (Alice) 没有到达 (Bob)(da) 范围以内,都按兵不动。一旦到了这个范围内,那么
    (Bob)(Alice) 的距离 (d(a,b)le da),那么我们马上让 (Bob) 走到一个和 (Alice) 距离为 (da+1) 的点 (v) 处, 因为 (d(b,a)le da), 那么 (d(b,a)+d(a,v)le da + da +1), 即 (d(b,v)le 2 imes da+1), 而 (db> 2 imes da),
    所以 (Bob) 是肯定能一次移动到这么一个点 (v) 的。那么 (Bob) 也就每次都能在被抓的边缘疯狂试探了:), 因此 (Bob) 赢。这里保证存在这么一个点 (v) 的前提条件就是我们已经排除了第二种情况,不会出现所有的点 (Alice) 都能在一步之内走到。
  • (db le 2 imes da), 这种情况,我们可以把 (Alice) 所在的点 (a) 看做是树的根节点,(b) 是在 (a) 的某个子树中的 (距离根节点 (v) 的距离大于 (da) ,而且会发现,因为 (db le 2 imes da), 所以 (a) 永远无法跳出它所在的子树到达另外一棵子树中去 (跳过去了也只会被抓到)。
    所以,我们只要每次让 (Alice)(b) 所在的子树下走一个节点 (这个时候 (d(a,b)) 最坏也只是变成 (2 imes da), 那么 (b) 依靠最大为 (2 imes da)(db) 还是跳不出对应的子树),然后一步一步逼近 (b) 就可以了,所以这种情况仍然是 (Alice) 赢。

求出 (a)(b) 的距离和 (da) 判断一下,然后求出树的直径, 和 (2 imes da) 比较一下, 最后用 (2 imes da) 再和 (db) 比较一下就可以了。

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5;

int n,a,b,da,db,d1,d2,nextX;
vector<int> g[N + 10];

void dfs1(int x,int fa,int mydis){
    if (x == b){
        d1 = mydis;
        return;
    }
    int len = g[x].size();
    for (int i = 0;i < len; i++){
        int y = g[x][i];
        if (y == fa){
            continue;
        }
        dfs1(y,x,mydis + 1);
    }
}

void dfs2(int x,int fa,int mydis){
    if (mydis > d2){
        nextX = x;
        d2 = mydis;
    }
    int len = g[x].size();
    for (int i = 0;i < len; i++){
        int y = g[x][i];
        if (y == fa){
            continue;
        }
        dfs2(y,x,mydis+1);
    }
}

int main(){
    #ifdef LOCAL_DEFINE
        freopen("E://9.AlgorithmCompetition//Visitor.txt","r",stdin);
    #endif
    ios::sync_with_stdio(0),cin.tie(0);
    int T;
    cin >> T;
    while (T--){
        for (int i = 1;i <= n; i++){
            g[i].clear();
        }
        cin >> n >> a >> b >> da >> db;
        for (int i = 1;i < n; i++){
            int x, y;
            cin >> x >> y;
            g[x].push_back(y);
            g[y].push_back(x);
        }
        dfs1(a, -1, 0);
        if (da >= d1){
            cout << "Alice" << endl;
            continue;
        }
        d2 = 0;nextX = 1;
        dfs2(a,-1,0);
        d2 = 0;
        dfs2(nextX,-1,0);
        if (2*da >= d2){
            cout << "Alice" << endl;
            continue;
        }
        if (db > da*2){
            cout << "Bob" << endl;
        }else{
            cout << "Alice" << endl;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/13634726.html