题解:
因为是树所以路径一定唯一,那么我们先算出a,b的lca为f1再算出c,d的lcaf2那么不难发现是求是否有重合路径,我们先把a到b的路径拆成a到f1和b到f1两条路径,那么就是求c到f2和前两个是否有重合或者d到f2是否与前两个有重合
#include<bits/stdc++.h>
using namespace std;
int head[100005];
int next[200005];
int ver[200005];
int d[100005];
int f[100005][25];
int tot=1,t;
int n,q;
int read(){
int num=0;
char ch=getchar();
while(ch>'9'||ch<'0'){
ch=getchar();
}
while(ch>='0'&&ch<='9'){
num=(num<<1)+(num<<3)+ch-'0';
ch=getchar();
}
return num;
}
void add(int x,int y){
ver[++tot]=y;
next[tot]=head[x];
head[x]=tot;
}
void dfs(int x,int fa){
d[x]=d[fa]+1;
for(int j=1;j<=t;j++){
f[x][j]=f[f[x][j-1]][j-1];
}
for(int i=head[x];i;i=next[i]){
if(d[ver[i]]) continue;
f[ver[i]][0]=x;
dfs(ver[i],x);
}
}
int lca(int x,int y){
if(d[x]>d[y]) swap(x,y);
for(int i=t;i>=0;i--){
if(d[f[y][i]]>=d[x]) y=f[y][i];
}
if(x==y){
return x;
}
for(int i=t;i>=0;i--){
if(f[x][i]!=f[y][i]){
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
int main(){
n=read();
t=log(n)/log(2)+1;
for(int i=1;i<n;i++){
int x=read(),y=read();
add(x,y);
add(y,x);
}
dfs(1,0);
q=read();
for(int i=1;i<=q;i++){
int a=read(),b=read(),c=read(),d=read();
int f1=lca(a,b),f2=lca(c,d);
if(lca(a,c)==c && lca(c,f1)==f1 || lca(a,d)==d && lca(d,f1)==f1)
printf("YES");
else if(lca(b,c)==c && lca(c,f1)==f1 || lca(b,d)==d && lca(d,f1)==f1)
printf("YES");
else if(lca(b,f2)==f2 && lca(f1,f2)==f1 || lca(a,f2)==f2 && lca(f1,f2)==f1)
printf("YES");
else if(lca(c,f1)==f1 && lca(f1,f2)==f2 || lca(d,f1)==f1 && lca(f1,f2)==f2)
printf("YES");
else
printf("NO");
if(q)putchar('\n');
}
return 0;
}