仓鼠找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;
    }
}
posted @ 2025-05-21 15:41  Marinaco  阅读(10)  评论(0)    收藏  举报
//雪花飘落效果