JZOJ5852. 【NOIP2018提高组模拟9.6】相交

这里写图片描述
这里写图片描述

题目大意

在一棵树上面,给出两条路径,判断是否有交集。

题解

利用路径的lca还有是否在子树里面就可简单的判断。

code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define N 100003
#define M 103
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    int w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int abs(int x){return x<0?-x:x;}
void write(int x){if(x>9) write(x/10);P(x%10+'0');}


int n,m,x,y,f[17][N],dep[N],xx,yy;
int nxt[N*2],to[N*2],lst[N],tot,lca1,lca2;

void ins(int x,int y)
{
    nxt[++tot]=lst[x];
    to[tot]=y;
    lst[x]=tot;
}

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

void dfs(int x)
{
    for(int i=lst[x];i;i=nxt[i])
        if(to[i]^f[0][x])f[0][to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
}

bool pd(int pos,int len)
{
    if(lca(lca1,pos)^lca1)return 0;
    if(dep[pos]-dep[lca(pos,x)]<=len)return 1;
    if(dep[pos]-dep[lca(pos,y)]<=len)return 1;
    return 0;
}

int main()
{
    freopen("inter.in","r",stdin);
    freopen("inter.out","w",stdout);

    read(n);
    for(int i=1;i<n;i++)
        read(x),read(y),ins(x,y),ins(y,x);

    dfs(dep[1]=1);
    for(int j=1;j<=16;j++)
        for(int i=1;i<=n;i++)
            f[j][i]=f[j-1][f[j-1][i]];

    for(read(m);m;m--)
    {
        read(x);read(y);read(xx);read(yy);
        lca1=lca(x,y);lca2=lca(xx,yy);
        if(pd(xx,dep[xx]-dep[lca2]) || pd(yy,dep[yy]-dep[lca2]))P('Y'),P('E'),P('S');
            else P('N'),P('O');
        P('\n');
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/lijf2001/article/details/82502863