- 若两条路径lca相同,则在lca处两者相交
- 两条路径相交点不可能在非lca处,即两条路径如果相交,一定是某一条路径的lca为另一条路径某个端点的祖先。
- 需要判断两条路径lca深度大小。再判断两次lca,做完了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<deque>
#include<cstdlib>
#include<ctime>
#define dd double
#define ld long double
#define ll long long
#define ull unsigned long long
#define N 100100
#define M 200200
using namespace std;
const int INF=0x3f3f3f3f;
inline ll read(){
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct edge{
int to,next;
inline void intt(int to_,int ne_){
to=to_;next=ne_;
}
};
edge li[M];
int head[N],tail;
inline void add(int from,int to){
li[++tail].intt(to,head[from]);
head[from]=tail;
}
int size[N],deep[N],top[N],son[N],fa[N];
inline void dfs1(int k,int f){
size[k]=1;deep[k]=deep[f]+1;fa[k]=f;
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(to==f) continue;
dfs1(to,k);
size[k]+=size[to];
if(size[to]>size[son[k]]) son[k]=to;
}
}
inline void dfs2(int k,int t){
top[k]=t;
if(!son[k]) return;
dfs2(son[k],t);
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(to==son[k]||to==fa[k]) continue;
dfs2(to,to);
}
}
inline int lca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
return x;
}
int n,q;
int main(){
n=read();q=read();
for(int i=1;i<=n-1;i++){
int from=read(),to=read();
add(from,to);add(to,from);
}
dfs1(1,0);dfs2(1,1);
for(int i=1;i<=q;i++){
int a1=read(),a2=read(),b1=read(),b2=read();
int lca1=lca(a1,a2),lca2=lca(b1,b2);
if(deep[lca1]>deep[lca2]){
int k1=lca(lca1,b1),k2=lca(lca1,b2);
if(k1==lca1||k2==lca1) printf("Y\n");
else printf("N\n");
}
else{
int k1=lca(lca2,a1),k2=lca(lca2,a2);
if(k1==lca2||k2==lca2) printf("Y\n");
else printf("N\n");
}
}
return 0;
}