傻逼题... 裸的树上路径交

  两条树上的路径$[a,b]$和$[c,d]$有交,则有$lca(a,b)$在$[c,d]$上或$lca(c,d)$在$[a,b]$上。

  其实只要深度大的$lca$在另一条链上就好了,所以设$x=lca(a,b)$深度较大。

  充分性证明:$x$在$[c,d]$上,则$[a,b]$和$[c,d]$显然有交。

  必要性证明:$x$不在$[c,d]$上,如果$[a,b]$上有点$y$与$[c,d]$有交,因为$lca(c,d)$深度较小,所以$y$的深度必定小于$x$,那么$x$就不是$lca(a,b)$了,矛盾,所以如果$x$不在$[c,d]$上,$[a,b]$与$[c,d]$无交。

  证毕。

  其实根本不用证明...太容易理解了...

  判断$x$在$[c,d]$上只需要判断$x$是$lca(c,d)$的儿子且$x$是$c$或$d$的父亲。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int maxn=500010;
struct poi{int too, pre;}e[maxn<<1];
int T, n, q, x, y, x2, y2, tot, tott;
int top[maxn], last[maxn], dep[maxn], l[maxn], r[maxn], size[maxn], son[maxn], fa[maxn];
inline void read(int &k)
{
    int f=1; k=0; char c=getchar();
    while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();
    while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
    k*=f;
}
inline void add(int x, int y){e[++tot]=(poi){y, last[x]}; last[x]=tot;}
void dfs1(int x)
{
    l[x]=++tott; size[x]=1;
    for(int i=last[x], too;i;i=e[i].pre)
    if((too=e[i].too)!=fa[x])
    {
        dep[too]=dep[x]+1; fa[too]=x;
        dfs1(too); size[x]+=size[too];
        if(size[too]>size[son[x]]) son[x]=too;
    }
    
    r[x]=tott;
}
void dfs2(int x, int tp)
{
    top[x]=tp;
    if(son[x]) dfs2(son[x], tp);
    for(int i=last[x], too;i;i=e[i].pre)
    if((too=e[i].too)!=fa[x] && too!=son[x]) dfs2(too, too);
}
inline int lca(int x, int y)
{
    int f1=top[x], f2=top[y];
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2]) swap(x, y), swap(f1, f2);
        x=fa[f1]; f1=top[x];
    }
    if(dep[x]<dep[y]) swap(x, y);
    return y;
}
bool check(int x, int y, int ls, int rs)
{
    if(l[x]<l[y] || r[y]<l[x]) return 0;
    if(l[x]<=l[ls] && l[ls]<=r[x]) return 1;
    if(l[x]<=l[rs] && l[rs]<=r[x]) return 1;
    return 0;
}
int main()
{
    read(T);
    while(T--)
    {
        memset(last, 0, sizeof(last)); tot=tott=0;
        read(n); read(q);
        for(int i=1;i<n;i++) read(x), read(y), add(x, y), add(y, x);
        dfs1(1); dfs2(1, 1);
        for(int i=1;i<=q;i++)
        {
            read(x); read(y); read(x2); read(y2);
            int f1=lca(x, y), f2=lca(x2, y2);
            if(dep[f1]<dep[f2]) swap(f1, f2), swap(x, x2), swap(y, y2);
            printf("%s\n", check(f1, f2, x2, y2)?"YES":"NO");
        }
    }
}
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-08-18
  • 2021-07-13
  • 2021-09-12
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案