P3398のハムスターは、砂糖を見つけます

\(説明\)

ある\(N- \)ツリーのノードは、あなたの各経路の両端点を与える\(A-> B、C-> D \) それは2つのパスの共通点があるかどうかを尋ねます

\(解決\)

ツリー共通点を分析すると、二つの経路がいる:シーク\(LCAを\)
2つのパスが共通点を持っている場合は、アップまたはさらに下のサブツリーになっチェーン下るように選択することが共通点に達します。
さらに、最後の点は、鎖またはダウンターンの共通終了持っている必要があります後に二つの鎖は、共通点が出ている、唯一の方法を取る

より明確に表示するには、この絵と一緒にを
チェーンが存在しなければならないように、包括両方\(LCA \)二本鎖のための必要十分条件は、交差され、他の鎖上に位置が、
点集合\(C \)を、この点は、鎖の両端点に位置している\(B \ )\(B \)\(LCA \)\(D \)、\ (DIS(D)+ DIS(D、C)+ DIS(B、C)は、DIS(、Bは= )\)
ツリーの性質に応じて唯一のパスであり、\(DIS(C)+ DIS(C、B)は、DIS(B)= \)

となぜなら可能の\(X- \)\(LCA \ )に位置し\(Y \)の両方のケースで検証がかかるので、チェーンは、順番に、ことも可能である\)\(または

\(コード\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define re register
#define maxn 200010
#define ll long long
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int q,a,b,c,d;
int tmp1,tmp2,tmp3,n,x,y,vis[maxn],f[maxn][23],lg[maxn],root;
int cnt,head[maxn],dep[maxn];
struct Edge{
    int v,nxt;
}e[maxn<<2];
inline void add(int u,int v)
{
    e[++cnt].v=v;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}
void dfs(int now,int fa)
{
    dep[now]=dep[fa]+1;
    f[now][0]=fa;
    for(int i=1;(1<<i)<=dep[now];++i)
     f[now][i]=f[f[now][i-1]][i-1]; 
    for(int i=head[now];i;i=e[i].nxt)
    {
        int ev=e[i].v;
        if(ev==fa) continue;
        dfs(ev,now);
    }
}
int lca(int x,int y)
{
    if(dep[y]>dep[x]) swap(x,y);
    for(re int i=lg[dep[x]-dep[y]];i>=0;--i)
    {
        if(dep[f[x][i]]<dep[y]) continue;
        x=f[x][i];
    }
    if(x==y) return x;
    for(re int i=lg[dep[x]-1];i>=0;--i)
    {
        if(f[x][i]==f[y][i]) continue;
        x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
void pre()
{
    tmp1=1,tmp2=0;
    while(tmp1<=n)
    {
        lg[tmp1]=tmp2;
        tmp2++;
        tmp1*=2;
    }
    for(re int i=1;i<=n;++i)
    {
        if(lg[i]) continue;
        lg[i]=lg[i-1];
    }
}
int dis(int a,int b)//计算一条链的长度 
{
    re int c=lca(a,b);
    return abs(dep[a]-dep[c])+abs(dep[b]-dep[c]);
}
int main()
{
    n=read(),q=read();
    pre();
    for(re int i=1;i<n;++i)
    {
        x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    dfs(1,0);
    for(re int i=1;i<=q;++i)
    {
        a=read(),b=read(),c=read(),d=read();
        tmp1=lca(a,b);
        tmp2=lca(c,d);
        if(dis(a,tmp2)+dis(b,tmp2)==dis(a,b)||dis(c,tmp1)+dis(d,tmp1)==dis(c,d)) printf("Y\n");
        else printf("N\n");
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/Liuz8848/p/11647060.html