BZOJ 1787 裸LCA

一个求树上LCA的裸题。。WC(伪。。)里想出来的。。

题目大意:给出树上的三个点,要求确定一个集合点,使得这三个点到集合点的路径权值和最小。所有边权均为1。

先考虑两个点A、B的情形。。显然这两个点间路径上的任何一点都可以作为集合点。。

然后再加入第三个点C。。画个图不难证明此时最优集合点应是LCA(A, B)。

但是A、B、C分别是哪个点呢?。。

枚举取最优解。。

但看了黄学长博客,给出了两种解法。。一种就是枚举,另一种则给出了一句结论,私认为很有道理。。

求出两两lca,其中有两个相同,答案则为另一个,画画图就可以理解”

这样的话,就可以直接确定是那一个LCA。。不用判断了。。

所以答案就很好搞了。。求求LCA加加就行了。。

用的是黄学长的模板。。

// BZOJ 1787

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

 typedef long long LL;
 typedef unsigned long long uLL;
 const int N=500000+5, INF=0x3f3f3f3f;

 #define rep(i,a,b) for (int i=a; i<=b; i++)
 #define dep(i,a,b) for (int i=a; i>=b; i--)
 #define read(x) scanf("%d", &x)
 #define fill(a,x) memset(a, x, sizeof(a))

 int n, q, dep[N], last[N], fa[N][20];

 struct Edge {
 	int to, pre;
 } e[N*2];  // 注意无向边数要乘2!

 int k=0;
 void ine(int x, int y) {
 	k++;
 	e[k].to=y; e[k].pre=last[x]; last[x]=k;
 	k++;
 	e[k].to=x; e[k].pre=last[y]; last[y]=k;
 }
 #define reg(i,a) for (int i=last[a]; i; i=e[i].pre)

 void change(int x, int dad) {  // 无根树转有根树的同时递推每个点的2^i祖先
 	rep(i,1,18) {
 		if (dep[x]<(1<<i)) break;
 		fa[x][i]=fa[fa[x][i-1]][i-1];
 	}
 	reg(i,x) {
 		int y=e[i].to;
 		if (y==dad) continue;
 		dep[y]=dep[x]+1;
 		fa[y][0]=x;
 		change(e[i].to, x);
 	}
 }

 int LCA(int x, int y) {
 	if (dep[x]<dep[y]) swap(x, y);
 	int d=dep[x]-dep[y];
 	rep(i,0,18) 
 		if ((1<<i)&d) x=fa[x][i];
 	dep(i,18,0) 
 		if (fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; }
 	if (x==y) return x; else return fa[x][0]; 
 }

 int dis(int x, int y) { int t=LCA(x,y); return dep[x]+dep[y]-2*dep[t]; }

 void solve(int x, int y, int z) {
 	int p1=LCA(x, y), p2=LCA(x, z), p3=LCA(y, z), p, ans;
 	if (p1==p2) p=p3; else if (p2==p3) p=p1; else p=p2;
 	ans=dis(x, p)+dis(y, p)+dis(z, p);
 	printf("%d %d\n", p, ans);
 }

int main()
{
	read(n); read(q);
	rep(i,1,n-1) {
		int u, v;
		read(u); read(v);
		ine(u, v);
	}
	change(1, 0);
	rep(i,1,q) {
		int x, y, z;
		read(x); read(y); read(z);
		solve(x, y, z);
	}
	
	return 0;
}



posted @ 2015-12-16 21:22  Armeria  阅读(600)  评论(0编辑  收藏  举报