codeforces 1304E 1-Trees and Queries LCA

﹥>﹥吖頭↗ 提交于 2020-03-17 03:29:10

https://vjudge.net/problem/CodeForces-1304E
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目大意:给一棵树,qq个询问(x,y,a,b,k)(x,y,a,b,k),表示在给xyx、y加一条边的情况下,问是否存在一条从aabb的经过了kk条边的路径,该路径可以多次经过同一个点、同一条边,但是起点必须是aa,终点必须是bb(有疑问的可看下样例)。
思路:找到一条从aabb的路径,设其经过了lenlen条边,只要len<=klen<=klenlenkk的奇偶性相同,就是有解的,因为一条边可以经过多次,所以只要(lenk)%2=0(len-k)\%2=0,缺少的边数就可以通过在一条边上循环往复来补足。因为xyx、y加了一条边,所以路径有三种选择:aba-baxyba-x-y-bayxba-y-x-b

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

const int maxn=1e5+5;

struct Edge
{
    int to,nxt;
}edge[maxn<<1];

int n,m,tot;
int head[maxn],deep[maxn],f[maxn][20],bs[20];

inline void addedge(int u,int v)
{
    edge[++tot].to=v,edge[tot].nxt=head[u],head[u]=tot;
}

void dfs(int u,int fa)
{
    f[u][0]=fa;
    for(int i=1;i<20;i++)
        f[u][i]=f[f[u][i-1]][i-1];
    int v;
    for(int i=head[u];i;i=edge[i].nxt)
    {
        v=edge[i].to;
        if(v==fa)
            continue;
        deep[v]=deep[u]+1;
        dfs(v,u);
    }
}

inline int skip(int x,int level)
{
    for(int i=19;i>=0;i--)
        if(bs[i]&level)
            x=f[x][i];
    return x;
}

inline int LCA(int u,int v)
{
    if(deep[u]<deep[v])
        swap(u,v);
    u=skip(u,deep[u]-deep[v]);
    if(u==v)
        return u;
    for(int i=19;i>=0;i--)
        if(f[u][i]!=f[v][i])
            u=f[u][i],v=f[v][i];
    return f[u][0];
}

inline int dis(int x,int y)
{
    int lca=LCA(x,y);
    return deep[x]+deep[y]-2*deep[lca];
}

inline bool work(int x,int y,int a,int b,int k)
{
    int len=dis(a,b);
    if(len<=k&&(len-k)%2==0)
        return 1;
    len=dis(a,x)+dis(b,y)+1;
    if(len<=k&&(len-k)%2==0)
        return 1;
    len=dis(a,y)+dis(b,x)+1;
    if(len<=k&&(len-k)%2==0)
        return 1;
    return 0;
}

int main()
{
    for(int i=0;i<20;i++)
        bs[i]=1<<i;
    scanf("%d",&n);
    int u,v;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        addedge(u,v),addedge(v,u);
    }
    dfs(1,0);
    int x,y,a,b,k;
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d%d%d%d%d",&x,&y,&a,&b,&k);
        printf("%s\n",work(x,y,a,b,k)?"YES":"NO");
    }
    return 0;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!