仓鼠找sugar
题目链接:https://www.luogu.com.cn/problem/P3398
题意:
给定两个起点以及两个终点构成的两条树上路径,询问是否相交
思路:
结论:当其中深度较大的起点,终点的lca,和另外一条路径上的起点或终点lca为它自己时,两条路径相交
注意倍增法求lca时,根节点的父亲是他自己。。
int n,q;
vector<int>e[maxn];
int dep[maxn];
int f[maxn][40];
void dfs1(int u,int fa,int now){
dep[u]=now;
f[u][0]=fa;
for(int i=1;i<=31;i++){
f[u][i]=f[f[u][i-1]][i-1];
}
for(int v:e[u]){
if(v==fa)continue;
dfs1(v,u,now+1);
}
}
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int i=30;i>=0;i--){
if(dep[f[u][i]]>=dep[v]){
u=f[u][i];
}
}
if(u==v)return u;
for(int i=30;i>=0;i--){
if(f[u][i]!=f[v][i]){
u=f[u][i];v=f[v][i];
}
}
return f[u][0];
}
void solve(){
cin>>n>>q;
rep(i,1,n-1){
int u,v;cin>>u>>v;
e[u].pb(v);e[v].pb(u);
}
dfs1(1,1,0);
while(q--){
int a,b,c,d;cin>>a>>b>>c>>d;
int u=lca(a,b),v=lca(c,d);
if(dep[u]<dep[v]){
swap(u,v);
swap(a,c);
swap(b,d);
}
// debug(u);
// debug(v);
// if(dep[u]==dep[v]){
// cout<<"Y"<<endl;continue;
// }
if(lca(u,c)==u||lca(u,d)==u)cout<<'Y'<<endl;
else cout<<"N"<<endl;
}
}