裸的LCA。
对于每次询问,设a,b的LCA为A,c,d的LCA为B,分两种情况讨论:
1)A与B的深度相同,此时二人相遇的充要条件为A==B,即四个点的最近公共祖先相同。
2 ) A与B深度不同,设A的深度大于B的深度,若二人相遇,则c或d与A的LCA一定为A。
#include<cstdio>
#include<vector>
#define maxn 100005
inline int fread(void){
char c;int num=0;
while((c=getchar())==' '||c=='\r'||c=='\n');
num+=c-'0';
while((c=getchar())>='0'&&c<='9')
num=num*10+c-'0';
return num;
}
inline void swap(int &a,int &b){
a^=b;b^=a;a^=b;
return;
}
int n,q,fa[maxn][20],deep[maxn];
std::vector<int>sons[maxn];
inline void dfs(int u,int f,int dep){
deep[u]=dep;fa[u][0]=f;
int v,mx=sons[u].size();
for(int i=0;i<mx;i++){
v=sons[u][i];
if(v!=f){
dfs(v,u,dep+1);
}
}
return;
}
inline int lca(int a,int b){
if(deep[a]<deep[b])swap(a,b);//make deep[a]>deep[b]
int i,j;
for(i=0;(1<<i)<=deep[a];++i);
--i;
for(j=i;j>=0;--j)
if(deep[a]-(1<<j)>=deep[b])
a=fa[a][j];
if(a==b)return a;
for(j=i;j>=0;--j)
if(fa[a][j]!=fa[b][j]&&fa[a][j]!=0)
a=fa[a][j],b=fa[b][j];
return fa[a][0];
}
int main(){
//freopen("a.in","r",stdin);
int i,j,k,x,y,a,b,c,d;
n=fread();q=fread();
for(i=0;i<n-1;++i){
x=fread();y=fread();
sons[x].push_back(y);
sons[y].push_back(x);
}//Initialize
dfs(1,0,0);
for(j=1;(1<<j)<=n;++j)
for(int i=1;i<=n;++i)
if(fa[i][j-1]!=-1)
fa[i][j]=fa[fa[i][j-1]][j-1];
//preprocess fathers
while(q){
a=fread();b=fread();
c=fread();d=fread();
int A=lca(a,b),B=lca(c,d);
if(deep[A]==deep[B]){
if(A==B)printf("Y\n");
else printf("N\n");
--q;continue;
}//case 1
if(deep[A]<deep[B]){
swap(A,B);swap(a,c);swap(b,d);
}//make deep[A]>deep[B]
if(lca(c,A)==A) printf("Y\n");
else if(lca(d,A)==A) printf("Y\n");
else printf("N\n");//case 2
--q;
}
return 0;
}