E. 1-Trees and Queries-1304(LCA倍增)

总结

求两点之间的距离------LCA
情况A:a-b的距离
情况B:a-x-y-b的距离
情况C:a-y-x-b的距离
dis<=k&&dis%2==k满足一个即可
之前我一直有一个疑问,为啥不用多跑一个环
假设
如果dis[a,x]+1+dis[y,b]<=dis[a,y]+1+dis[x,a];
那么a到b经过x,y取最短路肯定是dis[a,x]+1+dis[y,b]
dis[a,y]+1+dis[x,a]这种就是跑了一个环的情况,不信,你画图瞧瞧

const int N=3e5+5;
int fat[N][21],h[N];
vector<int>G[N];
void dfs(int x)
{
    for(auto v:G[x])
    {
        if(v==fat[x][0])
            continue;
        h[v]=h[x]+1;
        fat[v][0]=x;
        dfs(v);
    }
}
int lca(int x,int y)
{
    if(h[x]<h[y])
        swap(x,y);
    for(int i=20;i>=0;i--)
        if( (h[x]-h[y])>>i )
            x=fat[x][i];
    if(x==y)
        return x;
    for(int i=20;i>=0;i--)
        if( fat[x][i]!=fat[y][i] )
            x=fat[x][i],y=fat[y][i];
    return fat[x][0];
}
int dis(int x,int y)
{
    return h[x]+h[y]-h[lca(x,y)]*2;
}
signed main()
{
    IOS;
    file();
    int n;
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        G[x].pb(y);
        G[y].pb(x);
    }
    dfs(1);
    for(int i=1;i<=20;i++)
        for(int j=1;j<=n;j++)
            fat[j][i]=fat[ fat[j][i-1] ][i-1];
    int m;
    cin>>m;
    while(m--)
    {
        int x,y,a,b,k;
        cin>>x>>y>>a>>b>>k;
        int flag=0;
        if(dis(a,b)%2==k%2&&dis(a,b)<=k)
            flag=1;
        if( (dis(a,x)+1+dis(b,y))%2==k%2 && (dis(a,x)+1+dis(b,y))<=k )
            flag=1;
        if( (dis(a,y)+1+dis(b,x))%2==k%2 && (dis(a,y)+1+dis(b,x))<=k )
            flag=1;
        cout<<(flag?"YES":"NO")<<endl;
    }
    return 0;
}

补充

后面,我自己又想了一下,既然C路径一定要走一个成环(x到y的最短路不为1),那么PA∪PB-PA∩PB==PC的一个环,所以C路径就是算了A路径+一个环路径。

const int N=3e5+5;
int fat[N][21],h[N];
vector<int>G[N];
void dfs(int x)
{
    for(auto v:G[x])
    {
        if(v==fat[x][0])
            continue;
        h[v]=h[x]+1;
        fat[v][0]=x;
        dfs(v);
    }
}
int lca(int x,int y)
{
    if(h[x]<h[y])
        swap(x,y);
    for(int i=20;i>=0;i--)
        if( (h[x]-h[y])>>i )
            x=fat[x][i];
    if(x==y)
        return x;
    for(int i=20;i>=0;i--)
        if( fat[x][i]!=fat[y][i] )
            x=fat[x][i],y=fat[y][i];
    return fat[x][0];
}
int dis(int x,int y)
{
    return h[x]+h[y]-h[lca(x,y)]*2;
}
signed main()
{
    IOS;
   // file();
    int n;
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        G[x].pb(y);
        G[y].pb(x);
    }
    dfs(1);
    for(int i=1;i<=20;i++)
        for(int j=1;j<=n;j++)
            fat[j][i]=fat[ fat[j][i-1] ][i-1];
    int m;
    cin>>m;
    while(m--)
    {
        int x,y,a,b,k;
        cin>>x>>y>>a>>b>>k;
        int dis1=dis(a,b),dis2=min(dis(a,x)+dis(y,b),dis(a,y)+dis(x,b))+1;
        if(dis1%2==k%2&&dis1<=k||dis2%2==k%2&&dis2<=k)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}
发布了130 篇原创文章 · 获赞 5 · 访问量 4975

猜你喜欢

转载自blog.csdn.net/weixin_44224825/article/details/104403105