luoguP4281

这个题目有好多人倍增求LCA会被卡成80分(包括第一次提交的我,然后,我在万神的教导下,使用了优化版的倍增,直接水过去了.....跑得还挺快,最大点700ms(没有优化前1500ms),好吧其实还是卡过去的,用了快读快写,不过这里优化的倍增求LCA还是值得拿起小本子记录一下的哈哈)

Code:

#include <bits/stdc++.h>
using namespace std;
int m = 0,n,Q;
int head[500005];
struct Edge{
	int next,to;
}edge[1000005];
int deep[500005],parent[500005][21];

void DFS(int x,int from);
void add(int from,int to);
int LCA(int x,int y);
inline int read();
int deal(int A,int B,int C);
int getlen(int A,int B);
inline void write(int x)
{
	if(x == 0)putchar('0');
	char b[30];
	int R = 0;
	while(x)
		R++,b[R] = x%10 + '0',x/=10;
	for(int i = R ; i >= 1 ; i --)
		putchar(b[i]);
}
int main()
{
	n = read() , Q = read();
	for(int i = 1 ; i <= n - 1; i ++)
	{
		int u,v;
		u = read() , v = read();
		add(u,v),add(v,u);
	}
	DFS(1,0);
	while(Q)
	{
		int A,B,C;
		A = read() , B = read() , C = read();
		write(deal(A,B,C)),putchar('\n');
		Q --;
	}
	return 0;
}

int getlen(int A,int B)//获取AB之间的路径长度
{
	return deep[A] + deep[B] - 2*deep[LCA(A,B)];
}

int deal(int A,int B,int C)
{
	int AB = LCA(A,B) , AC = LCA(A,C) , BC = LCA(B,C);
	int ansAB,ansAC,ansBC;
	ansAB = getlen(A,AB) + getlen(B,AB) + getlen(C,AB);
	ansAC = getlen(A,AC) + getlen(B,AC) + getlen(C,AC);
	ansBC = getlen(A,BC) + getlen(B,BC) + getlen(C,BC);
	if(ansAB <= ansBC && ansAB <= ansAC)
	{
		write(AB);putchar(' ');
		return ansAB;
	}
	if(ansAC <= ansBC && ansAC <= ansAB)
	{
		write(AC);putchar(' ');
		return ansAC;
	}
	if(ansBC <= ansAB && ansBC <= ansAC)
	{
		write(BC);putchar(' ');
		return ansBC;
	}
}

int LCA(int x,int y)
{
	if(deep[x] > deep[y])swap(x,y);
	for(int i = log2(deep[y] - deep[x]) + 1 ; i >= 0 ; i --)
		if(deep[parent[y][i]] >= deep[x])
			y = parent[y][i];
	if(x == y)return x;
	for(int i = log2(deep[x])+1 ; i >= 0 ; i --)
		if(parent[x][i] != parent[y][i])
		x = parent[x][i] , y = parent[y][i];
	return parent[x][0];
}

void DFS(int x,int from)
{
	deep[x] = deep[from] + 1;
	parent[x][0] = from;
	for(int i = 1 ; i <= 20 ; i ++)
		parent[x][i] = parent[parent[x][i-1]][i-1];
	for(int i = head[x] ; i ; i = edge[i].next)
	{
		int to = edge[i].to;
		if(! deep[to])DFS(to , x);
	}
	return ;
}

void add(int from,int to)
{
	m++;
	edge[m].to = to;
	edge[m].next = head[from];
	head[from] = m;
}

inline int read()
{
	int x = 0,flag = 1;
	char ch = getchar();
	for( ; ch > '9' || ch < '0' ; ch = getchar())if(ch == '-')flag = -1;
	for( ; ch >= '0' && ch <= '9' ; ch = getchar())x = (x << 3) + (x << 1) + ch - '0';
	return x * flag;
}
posted @ 2020-10-24 16:22  MYCui  阅读(63)  评论(0编辑  收藏  举报