Borrow Classroom (LCA模板)

题目链接:https://ac.nowcoder.com/acm/contest/5086/C

想法:

简单的LCA的板子题吧。

只需要先分类讨论一下:   

学生的距离 < 老师的距离    ,  那么肯定是追不上了

学生的距离 == 老师的距离  , 如果此时它们的 LCA 不是教务处的位置就可以,不然不可以

学生的距离 > 老师的距离    ,  直接在教务处等就可以了

#pragma GCC optimize(3,"Ofast","inline")//O3优化
#pragma GCC optimize(2)//O2优化
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <ctime>
#include <bitset>
#include <cmath>
#include <sstream>
#include <iostream>

#define LL long long
#define ls nod<<1
#define rs (nod<<1)+1
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define INF 0x3f3f3f3f
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)

const double eps = 1e-10;
const int maxn = 1e5 + 10;
const int mod = 10;

int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
using namespace std;

int head[maxn];
int cnt;
int dep[maxn],f[maxn][21];
int MAXDEPTH;

struct edge {
    int to,nxt;
}e[maxn<<1];

void add_edge(int u,int v) {
    e[++cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;

    e[++cnt].to = u;
    e[cnt].nxt = head[v];
    head[v] = cnt;
}
void init() {
    MAXDEPTH = 20;
    cnt = 0;
    memset(f,0, sizeof(f));
    memset(head,-1, sizeof(head));
}
void dfs(int u,int fa) {
    dep[u] = dep[fa] + 1;
    for (int i = 1;(1 << i) <= dep[u];i++) {
        f[u][i] = f[f[u][i-1]][i-1];
    }
    for (int i = head[u];~i;i = e[i].nxt) {
        if (e[i].to != fa) {
            f[e[i].to][0] = u;
            dfs(e[i].to,u);
        }
    }
}

int LCA(int u,int v) {
    if (dep[u] > dep[v])
        swap(u,v);
    int hu = dep[u],hv = dep[v];
    for (int det = hv - hu,i = 0;det;det >>= 1,i++) {
        if (det & 1)
            v = f[v][i];
    }
    if (u == v)
        return u;
    for (int i = MAXDEPTH - 1;i >= 0;i--) {
        if (f[u][i] == f[v][i])
            continue;
        u = f[u][i];
        v = f[v][i];
    }
    return f[u][0];
}

int main() {
    int T;
    scanf("%d",&T);
    while (T--) {
        init();
        int n,q;
        scanf("%d%d",&n,&q);
        for (int i = 0;i < n-1;i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            add_edge(u,v);
        }
        dep[0] = -1;
        dfs(1,0);
        while (q--) {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if (b == c && b == 1) {
                printf("NO
");
                continue;
            }
            int dis1 = dep[b] + dep[c] - 2 * dep[LCA(b,c)] + dep[c];
            int dis2 = dep[a];
            if (dis1 < dis2) {
                printf("NO
");
            }
            else if (dis1 > dis2) {
                printf("YES
");
            }
            else {
                if (LCA(a,c) == 1)
                    printf("NO
");
                else
                    printf("YES
");
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/-Ackerman/p/12818279.html