• P3398 仓鼠找sugar 又一次血的教训


    做什么题都要注意数组的大小,不要犯下数组越界的错误(温馨(狠心)提示);

    做了好多遍就是不对,原来是【20】的数组,在for下循环1——》20,神奇爆零;

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

    这道题有一个性质:

    判断树上两条路径是否有交点或重叠部分,那就是

    有a,b一条路径,还有c,d这条路径。

    要是这两条路径相交或重合,

    那么要不是lca(a,b)在cd上,就是lca(c,d)在ab上;

    显然易得啊(反正我是不会证明,背下来记好了);

    倍增lca

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=2000050;
    int pre[maxn],other[maxn],last[maxn],l;
    int n,q;
    void add(int x,int y)
    {
        l++;
        pre[l]=last[x];
        last[x]=l;
        other[l]=y;
    }
    int dep[maxn],jump[maxn][20];
    void dfs(int u)
    {
        for(int p=last[u];p;p=pre[p])
        {
            int v=other[p];
            if(v==jump[u][0]) continue;
            dep[v]=dep[u]+1;
            jump[v][0]=u;
            dfs(v);
        }
    }
    
    int lca(int u,int v)
    {
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=0;i<=17;i++)
        {
            if((dep[u]-dep[v])&(1<<i)) u=jump[u][i];
        }
        if(u==v) return u;
        for(int j=17;j>=0;j--)
        {
            if(jump[u][j]!=jump[v][j])
            {
                u=jump[u][j];
                v=jump[v][j];
            }
        }
        return jump[u][0];
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        dfs(1);
        for(int j=1;j<=17;j++)//17就够了,不要搞什么20 
        {
            for(int i=1;i<=n;i++)
            {
                jump[i][j]=jump[jump[i][j-1]][j-1];
            }
        }
        for(int i=1;i<=q;i++)
        {
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            int x=lca(a,b);
            int y=lca(c,d);
            int l1=dep[a]+dep[b]-2*dep[x];//a->b路径长度 
            int l2=dep[c]+dep[d]-2*dep[y];//c->d路径长度 
            if(dep[c]+dep[x]-2*dep[lca(x,c)]+dep[d]+dep[x]-2*dep[lca(x,d)]==l2)//c->x->d==l2
            {
                printf("Y
    ");
                continue;
            }
                if(dep[a]+dep[y]-2*dep[lca(a,y)]+dep[b]+dep[y]-2*dep[lca(y,b)]==l1)//a->y->b==l1,就是两条线段长度和等于整个线段长度 
            {
                printf("Y
    ");
                continue;
            }
            printf("N
    ");
        }
        return 0;
    }
  • 相关阅读:
    防雪崩利器:熔断器 Hystrix 的原理与使用
    SpringBoot返回结果为null或空值不显示处理方法
    Tomca原理分析之责任链
    TOMCAT原理详解及请求过程
    RocketMQ支持事务消息机制
    ubuntu 安装rocketmq
    Monkey安装与配置教程
    Monkey通过安装包获取包名
    git使用笔记
    Linux解压命令
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11065570.html
Copyright © 2020-2023  润新知