LCA的基本操作,
判断两条路径是否相交,如果相交,记 x=lca(a,b),y=lca(c,d),则必有x在c~d路径上或y在a~b路径上
若有一个点在某条路径上,那么该点到路径两端点的距离和等于两端点的距离,距离用lca和深度就可以了
#include<cstdio> #include<iostream> #include<cmath> using namespace std; const int maxn=100010; int n,m,p,q,cnt; int head[maxn],dep[maxn],fa[maxn][30]; struct node{ int to,nxt; }e[200100]; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();} return s*w; } void add(int from,int to){ cnt++; e[cnt].to=to; e[cnt].nxt=head[from]; head[from]=cnt; } void dfs(int rt,int f){ dep[rt]=dep[f]+1; fa[rt][0]=f; for(int i=1;(1<<i)<=dep[rt];++i) fa[rt][i]=fa[fa[rt][i-1]][i-1]; for(int i=head[rt];i;i=e[i].nxt) if(e[i].to!=f) dfs(e[i].to,rt); } int lca(int x,int y){ if(dep[x]>dep[y])swap(x,y); for(int i=20;i>=0;i--) if(dep[x]<=dep[fa[y][i]])y=fa[y][i]; if(x==y)return x; for(int i=20;i>=0;i--){ if(fa[x][i]==fa[y][i])continue; x=fa[x][i]; y=fa[y][i]; } return fa[x][0]; } int dis(int x,int y){ int dd=lca(x,y); return abs(dep[x]-dep[dd])+abs(dep[y]-dep[dd]); } int main(){ n=read();m=read(); int x,y; for(int i=1;i<n;++i){ x=read();y=read(); add(x,y);add(y,x); } dfs(1,0); int z,k; for(int i=1;i<=m;++i){ x=read();y=read();z=read();k=read(); p=lca(x,y); q=lca(z,k); if(dis(z,p)+dis(k,p)==dis(z,k)||dis(x,q)+dis(y,q)==dis(x,y)) printf("Y "); else printf("N "); } return 0; }