zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    golang的reflect
    minium-介绍
    selenium+Node.js在windows下的配置和安装
    Jmeter-逻辑控制器之Switch控制器(Switch Controller)
    Jmeter-逻辑控制器之Foreach
    chrome插件-YSlow 一个使用的web性能测试插件
    jmeter
    Jmeter-从数据库中获取数据并作为变量传输
    Jmeter-无法启动,'findstr'不是内部或外部命令,也不是可运行的程序
    Jmeter-响应结果unicode转成中文显示
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11065570.html
Copyright © 2011-2022 走看看