[2020 Niu Ke Duo School] 9th Kグラウンドホッグのフリープラン——BFS

トピックリンク

題名


ポイントAにはツリーA があり、ポイント2にはB があります。A
の移動速度は1秒あたり1エッジを歩くことであり、Bの移動速度は
t秒前に2エッジ(または1つだけ)を歩くことです。 Bに移動し、Bは移動せず、
その後Bが移動を開始し、Aを追跡し始め、Aは逃げ始めます。
遅くともAが追跡される時期を尋ねます

分析

まず、ツリー上の任意の2点間のパスは一意であるため、t秒でのAの位置は固定されます。したがって、Bをルートとして使用し、ツリー乗算法を使用して、Aのt番目の祖先、つまりAが始まる場所をすばやく見つけることができます。
次に、AとBは、各ポイントに到達する状況を考慮して、Aが各ポイントに到達するのに必要な時間とBが各ポイントに到達するのにかかる時間を考慮して、追跡を開始します。 、これはAとBが最初にこのポイントに到達する時間です。次に、Aから開始して、同じ到着時間を持つ最大のポイントを見つけます。

ACコード

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 100;

vector<int> g[N];

int anc[N][20];
bool visit[N];

void dfs(int u, int fa) {
    
    
    anc[u][0] = fa;
    for (int i = 1; i <= 19; i++) anc[u][i] = anc[anc[u][i - 1]][i - 1];
    for (auto &v: g[u])
        if (v != fa) dfs(v, u);
}

int kthFa(int u, int k) {
    
    
    int bit = 0;
    while (k) {
    
    
        if (k & 1) u = anc[u][bit];
        k >>= 1;
        bit++;
    }
    return u;
}

int mouseTime[N], catTime[N];

void solve() {
    
    
    int n, t;
    cin >> n >> t;
    for (int i = 0; i < n - 1; ++i) {
    
    
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(n, 0);

    int kf = kthFa(1, t);
    if (kf == 0) kf = n;

    queue<pair<int, int>> q;
    memset(visit, false, sizeof(bool) * (n + 10));
    q.push({
    
    kf, 0});

    while (!q.empty()) {
    
    
        auto cur = q.front();
        q.pop();
        mouseTime[cur.first] = cur.second;
        visit[cur.first] = true;

        for (auto item : g[cur.first]) {
    
    
            if (visit[item]) continue;
            q.push({
    
    item, cur.second + 1});
        }
    }

    memset(visit, false, sizeof(bool) * (n + 10));
    q.push({
    
    n, 0});

    while (!q.empty()) {
    
    
        auto cur = q.front();
        q.pop();
        catTime[cur.first] = cur.second;
        visit[cur.first] = true;

        for (auto item : g[cur.first]) {
    
    
            if (visit[item]) continue;
            q.push({
    
    item, cur.second + 1});
        }
    }

    memset(visit, false, sizeof(bool) * (n + 10));
    q.push({
    
    kf, 0});

    int ans = 0;
    while (!q.empty()) {
    
    
        auto cur = q.front();
        q.pop();
        visit[cur.first] = true;

        ans = max(ans, max((catTime[cur.first] + 1) / 2, mouseTime[cur.first]));

        if ((catTime[cur.first] + 1) / 2 <= mouseTime[cur.first]) {
    
    
            continue;
        }

        for (auto item : g[cur.first]) {
    
    
            if (visit[item]) continue;
            q.push({
    
    item, 0});
        }
    }

    cout << ans << endl;
}

signed main() {
    
    
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed localTestCount = 1, localReadPos = cin.tellg();
    char localTryReadChar;
    do {
    
    
        if (localTestCount > 20)
            throw runtime_error("Check the stdin!!!");
        auto startClockForDebug = clock();
        solve();
        auto endClockForDebug = clock();
        cout << "Test " << localTestCount << " successful" << endl;
        cerr << "Test " << localTestCount++ << " Run Time: "
             << double(endClockForDebug - startClockForDebug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (localReadPos != cin.tellg() && cin >> localTryReadChar && localTryReadChar != '$' &&
             cin.putback(localTryReadChar));
#else
    solve();
#endif
    return 0;
}

おすすめ

転載: blog.csdn.net/m0_43448982/article/details/107881880