zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    Unity ShaderLab学习总结
    shader内置变量
    关于Unity中Shader的内置值
    Canvas控件最后一蛋——CanvasGroup
    Unity中关于Device Filter的选择问题
    Unity中使用扩展方法解决foreach导致的GC
    如何精简Unity中使用的字体文件
    好插件让你事半功倍!【资源篇】
    BFC(块级格式化上下文)的作用及生产方法
    获取视频或者音频时长
  • 原文地址:https://www.cnblogs.com/AWCXV/p/13634726.html
Copyright © 2011-2022 走看看