AHOI2008 聚会

洛谷

BZOJ

分析

任意两个点的最短距离一定经过它们的 \(LCA\) ,推广到三个点的情况,设这三个点分别是 \(x,y,z\) ,先求出 \(x, y\)\(LCA\)\(w\) ,最后的 \(pos\) 可能是在 \(w\)\(z\)\(LCA\) 处,但不难发现, \(w\) 是两个人在走,而 \(z\) 只有一个人,所以将 \(pos\) 放在 \(w\) 处显然会更合适。最后,手推样例发现三个 \(LCA\) 中取深度最大的 \(LCA\) 最合适。

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define il inline
#define re register
#define maxn 500003
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
typedef long long ll;

template <typename T> inline void read(T &x) {
    T f = 1; x = 0; char c;
    for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    x *= f;
}

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

int n, m, pos, cost;
int head[maxn], cnt;
int fa[maxn][25], dep[maxn], lg[maxn];

void addedge(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 dfs(int u, int _fa) {
    fa[u][0] = _fa, dep[u] = dep[_fa] + 1;
    for (int i = 1; (1 << i) <= dep[u]; ++i) fa[u][i] = fa[fa[u][i-1]][i-1];
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (v == _fa) continue;
        dfs(v, u);
    }
}

int LCA(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    while (dep[u] > dep[v]) u = fa[u][lg[dep[u]-dep[v]]-1];
    if (u == v) return u;
    for (int i = lg[dep[u]]; i >= 0; --i)
        if (fa[u][i] != fa[v][i])
            u = fa[u][i], v = fa[v][i];
    return fa[u][0];
}

void solve(int x, int y, int z) {
    int f1, f2, f3;
    f1 = LCA(x, y), f2 = LCA(y, z), f3 = LCA(x, z);
    pos = dep[f1] > dep[f2] ? f1 : f2;
    pos = dep[pos] > dep[f3] ? pos : f3;
    cost = dep[x] + dep[y] + dep[z] - dep[f1] - dep[f2] - dep[f3];
}

int main() {
    int u, v, w;
    read(n), read(m);
    for (int i = 1; i <= n; ++i) lg[i] = lg[i-1] + (1 << lg[i-1] == i);
    for (int i = 1; i < n; ++i) {
        read(u), read(v);
        addedge(u, v);
    }
    dfs(1, 0);
    for (int i = 1; i <= m; ++i) {
        cost = 0;
        read(u), read(v), read(w);
        solve(u, v, w);
        printf("%d %d\n", pos, cost);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hlw1/p/11437298.html