zoukankan      html  css  js  c++  java
  • CodeForces

    Tree Tag

    题目大意:

    有一棵(n)个点的树,(Alice)(Bob)起初分别在树上的节点(a)(b)

    他们轮流在树上移动一段距离不超过(da)(db)的路径。

    两点间的路径长度为两点间树上简单路径的边数。

    如果(Alice)能在无限次追及中追到(Bob),则(Alice)赢,否则(Bob)赢。

    思路:

    设树的直径为(tree_d)

    共有三种情况(Alice)能够获胜。

    1. (dis(a, b) leq da),即(Alice)能够一步追到(Bob)
    2. (da geq frac{db}{2}),即(Alice)能够步步逼近(Bob)
    3. (frac{tree_d}{2} leq da),即Alice的移动范围大于等于树的半径,则Alice只需到达直径的中心即获胜。

    我们只需通过树形(DP)(O(n))时间内求出树的直径,判断一下(da)(db)(tree_d)以及(dis(a, b))之间的关系即可。

    Code:
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 200010;
    
    vector<int> G[N];
    int dp[2][N];
    int dis[N];
    int tree_d;
    
    void dfs(int u, int pre) { //树形DP求树的直径
        for (int v : G[u]) {
            if (v == pre) continue;
            dis[v] = dis[u] + 1;
            dfs(v, u);
            if (dp[0][v] + 1 > dp[0][u]) {
                dp[1][u] = dp[0][u];
                dp[0][u] = dp[0][v] + 1;
            } else if (dp[0][v] + 1 > dp[1][u]) {
                dp[1][u] = dp[0][v] + 1;
            }
        }
        tree_d = max(dp[0][u] + dp[1][u], tree_d);
    }
    
    int main() {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int T; cin >> T;
        while (T--) {
            int n, a, b, da, db; cin >> n >> a >> b >> da >> db;
            //init
            tree_d = 0;
            for (int i = 0; i <= n; i++) {
                dis[i] = dp[0][i] = dp[1][i] = 0; G[i].clear();
            }
    
            for (int i = 1; i < n; i++) {
                int x, y; cin >> x >> y;
                G[x].push_back(y); G[y].push_back(x);
            }
            dfs(a, 0);
            if (dis[b] <= da) {
                cout << "Alice" << endl; continue;
            }
            if (2 * da >= db) {
                cout << "Alice" << endl; continue;
            }
            if (tree_d <= 2 * da) {
                cout << "Alice" << endl; continue;
            }
            cout << "Bob" << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    C++ 友元(friend关键字)、类中的重载、操作符重载(operator关键字)
    C++ 二阶构造模式
    C++ 对象构造顺序、构析函数、临时对象。
    C++ 初始化列表
    C++ 对象的构造
    C++ 类学习笔记 :: 作用域限定符
    linux和window下生成任意大小的文件
    RobotFramework和Eclipse集成-安装和使用说明
    Linux中判断一个命令是否执行成功
    xpath 轴定位表达方式
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/13724614.html
Copyright © 2011-2022 走看看