P4281 [AHOI2008]紧急集合 聚会 题解
就是求三个点到同一个点的最短路径。
Solution
我们知道在一颗树上,三个点的 \(LCA\) 只有两个点。
那最后肯定是移动到其中一个点上。
那移动到哪个点上更优呢。
我们都求出来然后取个 \(\min\) 不就行了嘛 /qd
于是这个蓝题就变成了 \(LCA\) 板子。
/*
Work by: TLE_Automation
*/
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
//#define int long long
using namespace std;
const int N = 1e6 + 10;
const int MAXN = 2e5 + 10;
inline char readchar() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
int res = 0, f = 0;char ch = readchar();
for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
return f ? -res : res;
}
inline void print(int x) {
if (x < 0 ) putchar('-'), x = -x;
if (x > 9 ) print(x / 10);
putchar(x % 10 + '0');
}
int n, Q, head[N], dep[N], f[N][30], num_adge = 0;
struct Node {int u, v, nxt;} e[N];
void add(int u, int v) {e[++num_adge] = (Node) {u, v, head[u]}, head[u] = num_adge;}
void dfs(int u, int fa) {
dep[u] = dep[fa] + 1, f[u][0] = fa;
for(int i = 1; i <= 20; i++)
f[u][i] = f[f[u][i - 1]][i - 1];
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v;
if(v ^ fa) dfs(v, u);
}
}
int LCA(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = 20; i >= 0; i--) {
if(dep[f[x][i]] >= dep[y]) x = f[x][i];
if(x == y) return x;
}
for(int i = 20; i >= 0; i--) {
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
}
return f[x][0];
}
int ans1 = 0, ans2 = 0;
int lca1, lca2;
int Ans;
signed main() {
n = read(), Q = read();
for(int i = 1, u, v; i <= n - 1; i++) u = read(), v = read(), add(u, v), add(v, u);
dfs(1, 0);
for(int i = 1; i <= Q; i++) {
int a = read(), b = read(), c = read();
int t1 = LCA(a, b), t2 = LCA(b, c), t3 = LCA(a, c);
// printf("\n%d %d %d\n\n", t1, t2, t3);
if(t1 == t2) {
lca1 = t1, lca2 = t3;
ans1 = dep[a] + dep[lca1] - 2 * dep[LCA(lca1, a)] + dep[b] + dep[lca1] - 2 * dep[LCA(lca1, b)] + dep[c] + dep[lca1] - 2 * dep[LCA(lca1, c)];
ans2 = dep[a] + dep[lca2] - 2 * dep[LCA(lca2, a)] + dep[b] + dep[lca2] - 2 * dep[LCA(lca2, b)] + dep[c] + dep[lca2] - 2 * dep[LCA(lca2, c)];
}
else if(t1 == t3) {
lca1 = t1, lca2 = t2;
ans1 = dep[a] + dep[lca1] - 2 * dep[LCA(lca1, a)] + dep[b] + dep[lca1] - 2 * dep[LCA(lca1, b)] + dep[c] + dep[lca1] - 2 * dep[LCA(lca1, c)];
ans2 = dep[a] + dep[lca2] - 2 * dep[LCA(lca2, a)] + dep[b] + dep[lca2] - 2 * dep[LCA(lca2, b)] + dep[c] + dep[lca2] - 2 * dep[LCA(lca2, c)];
}
else if(t2 == t3) {
lca1 = t2, lca2 = t1;
ans1 = dep[a] + dep[lca1] - 2 * dep[LCA(lca1, a)] + dep[b] + dep[lca1] - 2 * dep[LCA(lca1, b)] + dep[c] + dep[lca1] - 2 * dep[LCA(lca1, c)];
ans2 = dep[a] + dep[lca2] - 2 * dep[LCA(lca2, a)] + dep[b] + dep[lca2] - 2 * dep[LCA(lca2, b)] + dep[c] + dep[lca2] - 2 * dep[LCA(lca2, c)];
}
if(ans1 < ans2) Ans = lca1;
else Ans = lca2;
printf("%d %d\n", Ans, min(ans1, ans2));
}
}