任意两个点的最短距离一定经过它们的 \(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;
}
原文:https://www.cnblogs.com/hlw1/p/11437298.html