P3398 仓鼠找sugar (一道LCA的裸题)

https://www.luogu.org/problemnew/show/P3398

题意简单概括一下就是求树上两条路径是否相交;

有这样一个性质:

if相交,则必有lca(a,b) 在路径c <-> d 上or lca(c,d) 在路径a <-> b 上;

接下来就是这样一个问题:

怎样判断一个点(x)是否在一条路径(a,b)上

如果满足以下两个条件,则在:

1.dep[x] >= lca(a,b);

2.lca(x,a) == x || lca(x,b) == x

#include <bits/stdc++.h>
#define read read()
#define up(i,l,r) for(register int i = (l);i <= (r);++i)
#define down(i,l,r) for(register int i = (l);i >= (r);i--)
#define traversal_vedge(i) for(register int i = head[u]; i ;i = e[i].nxt)
#define ll long long
using namespace std;
int read
{
    int x = 0, f = 1; char ch = getchar();
    while(ch < 48 || ch > 57) {if(ch == '-')f = -1; ch = getchar();}
    while(ch >=48 && ch <=57) {x = 10 * x + ch - 48;ch = getchar();}
    return x * f; 
}
//-----------------------------------------------------------------
const int N = 100005;
int n,q;

struct edge{
    int v,nxt;
}e[N<<1];int tot,head[N];

void buildtree(int u,int v) {e[++tot] = (edge){v,head[u]}; head[u] = tot;}
//-----------------------------------------------------------------

int dep[N],size[N],top[N],fa[N];
void initdfs(int u){
    dep[u] = dep[fa[u]] + 1;
    size[u] = 1; top[u] = u;
    int hson_id = 0,hson_size = 0;
    traversal_vedge(i)
    {
        int v = e[i].v;
        if(fa[u] == v) continue;
        fa[v] = u;
        initdfs(v);
        size[u] += size[v];
        if(size[v] > hson_size) hson_id = v,hson_size = size[v];
    }
    if(hson_id) top[hson_id] = u;
}
int find(int u){if(top[u] == u) return u;top[u] = find(top[u]); return top[u];}
int lca(int x,int y){
    if(find(x) != find(y)){
        if(dep[top[x]] > dep[top[y]]) return lca(fa[top[x]],y);
        else return lca(x,fa[top[y]]);
    }
    return dep[x] > dep[y] ? y : x;
}
//-----------------------------------------------------------------
bool ok;
void query(int x,int a,int b){
    if(lca(a,x) == x || lca(b,x) == x) ok = 1;
}

void work(){
    initdfs(1);
    while(q--)
    {
        ok = 0;
        int a = read,b = read,c = read,d = read;
        int x = lca(a,b);int y = lca(c,d);//debug y = lca(a,b)
        if(dep[x] >= dep[y]) query(x,c,d);
        if(!ok) if(dep[y] >= dep[x]) query(y,a,b);
        if(ok == 1) printf("Y\n");
         else printf("N\n");
     }
} 

void readdata(){
    n = read; q = read;
    up(i,1,n-1)
    {
        int u = read,v = read;
        buildtree(u,v);
        buildtree(v,u);
    }    
}

int main()
{
    readdata();
    work();
    return 0;
}

 

转载于:https://www.cnblogs.com/mzg1805/p/10418921.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值