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;
}
By MYCui