zoukankan      html  css  js  c++  java
  • 用树链剖分来写LCA

    当两个点在一条链上,它们的LCA就是深度较小的那个点。

    于是这种树链剖分写LCA的思想就是把要求的两个点想办法靠到一条链上。

    而且要靠到尽量更优的一条链上(重链)。 

    做法:

    预处理出每棵树上的重链(size大的),每个点求出一个top,代表与这个点能靠到最近的一条重链的位置。

    求LCA时两个点分别向各自top移动,直到两个点到一条链上,输出深度较小的

    细节见代码

    #include<cstdio>
    #include<iostream>
    #define MAXN 500001
    using namespace std;
    struct edge{int pre,other;}b[MAXN*2];
    struct node{int last,p,depth,h,child,top;}a[MAXN];
    int cnt,N,M,x,y,l,root;
    void connect(int x1,int x2)
    {
        b[++cnt]=(edge){a[x1].last,x2};
        a[x1].last=cnt;
    }
    void dfs1(int x1)                  //第一次dfs预处理size、深度,求出重链 (变量名错了 h就是size)
    {
        a[x1].depth=a[a[x1].p].depth+1;
        a[x1].h=1;
        for(int i=a[x1].last;i;i=b[i].pre)
        {
            int x2=b[i].other;
            if(!a[x2].p&&a[x1].p!=x2)
            {
                a[x2].p=x1;
                dfs1(x2);
                a[x1].h+=a[x2].h;
                if(a[a[x1].child].h<a[x2].h)a[x1].child=x2;
            }
        }
    }
    void dfs2(int x1)                    //第二次dfs预处理top
    { 
        if(x1==a[a[x1].p].child)a[x1].top=a[a[x1].p].top;            
        else a[x1].top=x1;
        for(int i=a[x1].last;i;i=b[i].pre)if(a[b[i].other].p==x1)dfs2(b[i].other);
    }
    int LCA(int x1,int x2)
    {
        while(a[x1].top!=a[x2].top)          
        {
            if(a[a[x1].top].depth>a[a[x2].top].depth)x1=a[a[x1].top].p;
            else x2=a[a[x2].top].p;          //深度大的点向top移动
        }
        return a[x1].depth<a[x2].depth?x1:x2;
    }
    int main()
    {
        scanf("%d%d%d",&N,&M,&root);
        for(int i=1;i<=N-1;i++)
        {
            scanf("%d%d",&x,&y);
            connect(x,y);
            connect(y,x);
        }
        dfs1(root);
        dfs2(root);
        while(M--)
        {
            scanf("%d%d",&x,&y);
            printf("%d
    ",LCA(x,y));    
        }
        return 0;
    }
  • 相关阅读:
    尝试消除switch
    JsUnit的测试套件
    GetCallbackEventReference对我来说太复杂了
    实现获取客户端的MAC地址(2)
    控件开发复习
    在VS2008的JScript编辑器中显示为命名空间
    函数参数修饰符out、ref及空白的区别
    检测代码位置的比较(C#代码VS存贮过程)
    发布时,正在使用的用户出错
    js特效,加速度,图标跳动
  • 原文地址:https://www.cnblogs.com/Elfish/p/7608694.html
Copyright © 2011-2022 走看看