zoukankan      html  css  js  c++  java
  • Codeforces Round #668 (Div. 2) D

    贪心, 很好玩一道题, 卡着近2h, 是真的nt, 单独写出来

    要么第一次抓到, 要么 min(直径, db) <= (da << 1)

    首先是第一次就被alice抓到, 没什么好说的

    然后是 db <= (da << 1), 那么alice就向bob靠近, bob只能朝着远离alice方向跑, 如果反向跑, bob跳不出alice捕捉范围, 由于10^100, 终将能抓到bob

    在 db > (da << 1) 就能跑了吗? 不能,看看样例的第三个数据为什么没跑掉? 没有足够的距离让bob, 风筝alice

    在能风筝alice, 且有足够距离风筝alice 且第一次不被抓到时,

    1.bob, alice 都在足够风筝的路径上(假设是直径), 那么第一抓不到bob, bob就可以控制距离(不断朝着远离alice的方向),

    直到bob可以直接跳过alice(向alice靠近的方向, 且直接越过ailice, 且没有跳出直径, 如果跳出直径, 那么说明你还可以向远离alice的方向走, 要么是直径不够风筝距离与前提矛盾)

    2.bob在直径上, alice不在, 那更好弄了, 在直径上控制好Alice进入直径的时候抓不到你, 你就可以同1,风筝alice

    3.bob不在, alice在直径, 由于第一次alice抓不到bob, bob就可以原地等待, 或者远离alice跑, 让alice靠近bob, 一直风筝alice和bob距离为da + 1, 一旦达到无法再跑时, 可以直接越过alice, 跑到直径上

    此时要么时状态1, 要么是状态2, 还是bob活

    就是因为3不好想, 挂机1个半多小时, 说白了还是直径理解不够, 只要bob能逃到直径且alice抓不到bob就赢了,

    bob所在分支和直径的连接点 C, 将直径分为x, y两段, 由于直径 > (da << 1), 那么必然 max(len(x), len(y)) > da, 只要bob按兵不动, 一旦进入alice射程, 就跑到(x, y)长的那一段上, 形成 1, 2局面

    #include <bits/stdc++.h>
    #define all(n) (n).begin(), (n).end()
    #define se second
    #define fi first
    #define pb push_back
    #define mp make_pair
    #define sqr(n) (n)*(n)
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i=(a);i>=(b);--i)
    #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> PII;
    typedef pair<ll, ll> PLL;
    typedef vector<int> VI;
    
    const int N = 1e5 + 5;
    
    int n, m, _, k;
    int h[N], to[N << 1], ne[N << 1], tot;
    int a, b, da, db;
    int f[N][20], dep[N], t, d[N];
    bool v[N];
    
    void add(int u, int v) {
        ne[++tot] = h[u]; to[h[u] = tot] = v;
    }
    
    void bfs(int s) {
        queue<int> q;
        q.push(s); dep[s] = 1;
        rep(i, 0, t) f[s][i] = 0;
     
        while (!q.empty()) {
            int x = q.front(); q.pop();
            for (int i = h[x]; i; i = ne[i]) {
                int y = to[i];
                if (dep[y]) continue;
                dep[y] = dep[x] + 1;
                f[y][0] = x;
     
                for (int j = 1; j <= t; ++j)
                    f[y][j] = f[f[y][j - 1]][j - 1];
     
                q.push(y);
            }
        }
    }
    
    int lca(int x, int y) {
        if (dep[x] > dep[y]) swap(x, y);
        per(i, t, 0)
            if (dep[f[y][i]] >= dep[x]) y = f[y][i];
    
        if (x == y) return x;
    
        per(i, t, 0)
            if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
    
        return f[x][0];
    }
    
    void dpfind(int u, int& ans) {
        v[u] = 1;
        for (int i = h[u]; i; i = ne[i]) {
            int y = to[i];
            if (v[y]) continue;
            dpfind(y, ans);
            ans = max(ans, d[u] + d[y] + 1);
            d[u] = max(d[u], d[y] + 1);
        }
        d[u] = max(d[u], 0);
    }
    
    int main() {
        IOS;
        for (cin >> _; _; --_) {
            cin >> n >> a >> b >> da >> db;
            tot = 0; t = log2(n - 1) + 1;
            rep(i, 1, n) h[i] = dep[i] = d[i] = v[i] = 0;
            rep(i, 2, n) {
                int u, v; cin >> u >> v;
                add(u, v); add(v, u);
            }
    
            bfs(a);
            int dr = 0; dpfind(a, dr);
    
            if (dep[b] - 1 <= da || min(db, dr) <= (da << 1))
                cout << "Alice
    ";
            else cout << "Bob
    ";
        }
        return 0;
    }
    
  • 相关阅读:
    所谓guard进程不能启动
    文件拒绝访问
    (转)Android 自定义 spinner (背景、字体颜色)
    (转)安装Android SDK时遇到Failed to rename directory
    (转)Download interrupted: Connection to https://dl-ssl.google.com refused
    安卓中Activity的onStart()和onResume()的区别是什么
    Could not find class 'org.ksoap2.serialization.SoapObject
    Android三种左右滑动效果 手势识别(转)
    The method of type must override a superclass method解决方式(转)
    MySQL插入中文时出现ERROR 1406 (22001): Data too long for column 'name' at row 1 (转)
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/13626127.html
Copyright © 2011-2022 走看看