P3398 仓鼠找sugar

很基础的lca题。

 

关键是弄明白什么时候两人会相遇,即什么情况下a-b与c-d的路径会相交

首先默认dep[a]>dep[b],dep[c]>dep[d],

那么一共有四种情况相交

if(lca(a,lca2)==lca2&&lca3==lca1) flag=1;
if(lca(b,lca2)==lca2&&lca3==lca1) flag=1;
if(lca(c,lca1)==lca1&&lca3==lca2) flag=1;
if(lca(d,lca1)==lca1&&lca3==lca2) flag=1;

其分别对应于

lca2在a-lca1的路径上

lca2在b-lca1的路径上

lca1在c-lca2的路径上

lca1在d-lca2的路径上

 

#include<bits/stdc++.h>

using namespace std;
const int maxn=100005;
int tail,head[maxn],f[maxn][21],dep[maxn],n,q;

struct edge
{
    int x,y,nex;
}e[400005];

void read(int &p)
{
    p=0;
    int flag=1;
    char s=getchar();
    while(!isdigit(s)) s=getchar();
    for(;isdigit(s);s=getchar()) p=p*10+s-'0';
    p*=flag;
}

void add_edge(int x,int y)
{
    e[++tail].x=x;e[tail].y=y;e[tail].nex=head[x];head[x]=tail;
}

void deal_first(int x,int fa)
{
    dep[x]=dep[fa]+1;
    for(int i=0;i<=19;i++) 
    f[x][i+1]=f[f[x][i]][i];
    
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].y;
        if(y!=fa)
        {
            f[y][0]=x;
            deal_first(y,x);
        }
    }
}

int lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=20;i>=0;i--)
    {
        if(dep[f[x][i]]>=dep[y]) x=f[x][i];
        if(x==y) return x;
    }
    
    for(int i=20;i>=0;i--)
    {
        if(f[x][i]!=f[y][i])
        {
            x=f[x][i];y=f[y][i];
        }
    }
    return f[x][0]; 
}

int main()
{
    #ifdef DEBUG
    //    freopen("1.in","r",stdin);
        #endif
    
    read(n);read(q);
    int x,y;
    for(int i=1;i<=n-1;i++)
    {
        read(x);read(y);
        add_edge(x,y);
        add_edge(y,x);
    }
    //build a tree
    deal_first(1,0);
    
    //read(q);
    //cout<<"A"<<q<<endl;
    int a,b,c,d;
    //deal with questions
    for(int i=1;i<=q;i++)
    {
        int flag=0;
        read(a);read(b);read(c);read(d);
        int lca1=lca(a,b);
        int lca2=lca(c,d);
        int lca3=lca(lca1,lca2);
        if(lca(a,lca2)==lca2&&lca3==lca1) flag=1;
        if(lca(b,lca2)==lca2&&lca3==lca1) flag=1;
        if(lca(c,lca1)==lca1&&lca3==lca2) flag=1;
        if(lca(d,lca1)==lca1&&lca3==lca2) flag=1;
        if(flag==1) puts("Y");
        else puts("N");
    }
    
    return 0;
} 

 

posted @ 2021-05-14 09:23  Adaxy  阅读(52)  评论(0编辑  收藏  举报