1. 程式人生 > 其它 >P4281 [AHOI2008]緊急集合 聚會 題解

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));
	}
}