[CF1404B] Tree Tag

[CF1404B] Tree Tag - 博弈论,树的直径

Description

给定一棵树,Alice 和 Bob 初始在 a,b 两点,每次移动的距离分别不超过 da,db,如果 Alice 能在 (10^{100}) 轮内追到 Bob 那么 Alice 赢,否则 Bob 赢。判断输赢。

Solution

如果 da >= dist(a,b),那么一步结束

如果 2 da >= diam,A 走到直径中点,那么下一步 A 一定能追到 B

如果 2 da >= db,A 不断逼近 B,最终 B 逃不出 A 下一步能走到的范围

其它情况下 B 在 A 靠近他时反向跳走,不会使得距离减小(否则必然满足上述条件中的一个)

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

#define int long long
const int N = 1000005;

int n, a, b, da, db, d[N];
vector<int> g[N];

void dfs(int p, int from)
{
    for (int q : g[p])
        if (q != from)
        {
            d[q] = d[p] + 1;
            dfs(q, p);
        }
}

void solve()
{
    cin >> n >> a >> b >> da >> db;
    for (int i = 1; i <= n; i++)
        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);
    }
    int pt = 0;
    d[1] = 0;
    dfs(1, 0);
    pt = max_element(d + 1, d + n + 1) - d;
    int diam = 0;
    d[pt] = 0;
    dfs(pt, 0);
    diam = *max_element(d + 1, d + n + 1);
    db = min(db, diam);
    int dab = 0;
    d[a] = 0;
    dfs(a, 0);
    dab = d[b];
    if (da >= dab || 2 * da >= db)
        cout << "Alice" << endl;
    else
        cout << "Bob" << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14398518.html