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;
}
posted @ 2019-08-30 21:50  小蒟蒻hlw  阅读(181)  评论(0)    收藏  举报