全WA,在其他OJ上能过
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cmath>
using namespace std;
inline int read(){
int s=0,w=1;
char c=getchar();
while(!isdigit(c)) {if(c=='-')w=-1;c=getchar();}
while(isdigit(c)) s=s*10+(c^48),c=getchar();
return s*w;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N = 500007;
int n , m , root;
int head[N] , e[N * 2] , ne[N * 2] , idx;
int depth[N * 2], fa[N * 2][27];
int q[N * 2];
inline void add(int a , int b)
{
e[idx] = b;
ne[idx] = head[a];
head[a] = idx;
idx ++;
}
inline void bfs(int u)
{//用bfs的最段路性质求depth
for(int i = 1 ; i <= N ; i ++) depth[i] = 1e9;
//假如有点出去了,就会变成depth[0]
depth[0] = 0 , depth[u] = 1;
int hh = 0 , tt = 0;
q[0] = u;
while(hh <= tt)
{
int t = q[hh];
++ hh;
for(int i = head[t] ; i != -1 ; i = ne[i])
{
int j = e[i];
if(depth[j] > depth[t] + 1)
{
depth[j] = depth[t] + 1;
++ tt;
q[tt] = j;
//向上走一格为亲爹
fa[j][0] = t;
//二进制处理祖宗
//两倍的二进制祖宗
for(int k = 1 ; k <= 20 ; ++ k)
{
fa[j][k] = fa[fa[j][k - 1]][k - 1];
}
}
}
}
}
inline int lca(int x , int y)
{
if(depth[x] < depth[y]) swap(x , y);
//先统一深度,这里depth[0]保证就算跳出去了也不会出现一些奇奇怪怪的错误
for(int i = 20 ; i >= 0 ; -- i) if(depth[fa[x][i]] >= depth[y]) x = fa[x][i];
if(x == y) return x;//当然y也可以
for(int i = 20 ; i >= 0 ; -- i)
{//从大到小跳,已经证明过了
if(fa[x][i] != fa[y][i])
{//假如跳出去了,很明显x必然等于y,这样就可以保证这个条件不成立
//则可以避免出现玄学错误
x = fa[x][i];
y = fa[y][i];
}
}
//会停在LCA前一个点,若停在LCA则有可能出现非最近公共祖先
return fa[x][0];
}
int main(){
n = read();m = read();root = read();
memset(head , -1 , sizeof(head));
for(int i = 1 ; i < n ; ++ i)
{
int a , b;
a = read();b = read();
if(a == b) continue;
add(a , b) , add(b , a);
}
bfs(root);//预处理深度,父亲数组
while(m --)
{
int a , b;
a = read();b = read();
int LCA = lca(a , b);
write(LCA);
}
return 0;
}