题目
多次询问求树上的两条路径是否有公共点
分析
有公共点当且仅当一条路径的LCA在另一条路径上,
否则一定会形成一个环,那树剖求LCA判断一下LCA是否在另一条路径上即可
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=100101;
struct node{int y,next;}e[N<<1];
int k=1,n,as[N],fat[N],dep[N],tot;
int son[N],dfn[N],top[N],big[N],m;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
for (rr int i=as[x],mson=-1;i;i=e[i].next)
if (e[i].y!=fa){
dfs1(e[i].y,x);
son[x]+=son[e[i].y];
if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y];
}
}
inline void dfs2(int x,int linp){
dfn[x]=++tot,top[x]=linp;
if (!big[x]) return; dfs2(big[x],linp);
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fat[x]&&e[i].y!=big[x])
dfs2(e[i].y,e[i].y);
}
inline signed lca(int x,int y){
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
x=fat[top[x]];
}
if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
return x;
}
inline signed dist(int x,int y){
rr int LCA=lca(x,y);
return dep[x]+dep[y]-2*dep[LCA];
}
signed main(){
n=iut(); m=iut();
for (rr int i=1;i<n;++i){
rr int x=iut(),y=iut();
e[++k]=(node){y,as[x]},as[x]=k,
e[++k]=(node){x,as[y]},as[y]=k;
}
dfs1(1,0),dfs2(1,0);
for (rr int i=1;i<=m;++i,putchar(10)){
rr int lx=iut(),ly=iut(),rx=iut(),ry=iut();
rr int lcal=lca(lx,ly),lcar=lca(rx,ry);
if (dist(lx,lcar)+dist(lcar,ly)==dist(lx,ly)){
putchar('Y'); continue;
}
if (dist(rx,lcal)+dist(ry,lcal)==dist(rx,ry)){
putchar('Y'); continue;
}
putchar('N');
}
return 0;
}