题目传送门:https://www.luogu.org/problemnew/show/P3398
这个题就是a,b,c,d四个点先分别求一下lca,然后假如其中一组的lca深度大于另一组中任意一个点的深度,那一定无解(因为根本就到不了同一高度)。另外的话我开始想的是假如成立,lca(lca(a,b),lca(c,d))一定等于lca(a,b)或lca(c,d),然而这是一个路径重叠的必要条件,并不是一个充分条件,也就是说他并不能推出路径重叠,给出一组例子,有九个节点的一棵完全二叉树,节点编号按广度优先遍历赋值,想一下8号到9号和5号到7号的关系。所以说还是要判断lca深度较深的组的lca与另一组中两个点分开来判断是不是他们的祖先。附上代码:
#include
#include
#include
int dep[200001]={0},to[500001]={0},nxt[500001]={0},head[200001]={0},dp[200001][25]={0};
int n,q,tmp=0;
int add(int x,int y)
{
tmp++;
to[tmp]=y;
nxt[tmp]=head[x];
head[x]=tmp;
return 0;
}
int dfs1(int son,int father)
{
int i,t;
dep[son]=dep[father]+1;
for(i=0;i<=19;i++)
dp[son][i+1]=dp[dp[son][i]][i];
for(i=head[son];i;i=nxt[i])
{
t=to[i];
if(t==father) continue;
dp[t][0]=son;
dfs1(t,son);
}
return 0;
}
int lca(int x,int y)
{
int i,t;
if(dep[x]=0;i--)
{
if(dep[dp[x][i]]>=dep[y]) x=dp[x][i];
if(x==y) return x;
}
for(i=20;i>=0;i--)
{
if(dp[x][i]!=dp[y][i])
{
x=dp[x][i];y=dp[y][i];
}
}
return dp[x][0];
}
int main()
{
int i,x,y,a,b,c,d,t1,t2,t3;
scanf("%d%d",&n,&q);
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs1(1,0);
for(i=1;i<=q;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
t1=lca(a,b);t2=lca(c,d);
if((dep[t1]>dep[c]&&dep[t1]>dep[d])||(dep[t2]>dep[a]&&dep[t2]>dep[b]))
{
printf("N\n");
continue;
}
if(dep[t1]>=dep[t2])
{
if(lca(t1,c)==t1||lca(t1,d)==t1)
printf("Y\n");
else printf("N\n");
}
else
{
if(lca(t2,a)==t2||lca(t2,b)==t2)
printf("Y\n");
else printf("N\n");
}
}
return 0;
}