题目描述

如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

输入输出格式

输入格式:

第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。

接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。

接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。

输出格式:

输出包含M行,每行包含一个正整数,依次为每一个询问的结果。

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,M<=10

对于70%的数据:N<=10000,M<=10000

对于100%的数据:N<=500000,M<=500000

样例说明:

该树结构如下:

第一次询问:2、4的最近公共祖先,故为4。

第二次询问:3、2的最近公共祖先,故为4。

第三次询问:3、5的最近公共祖先,故为1。

第四次询问:1、2的最近公共祖先,故为4。

第五次询问:4、5的最近公共祖先,故为4。

故输出依次为4、4、1、4、4。

思路:

这道题是最近公共祖先的模板题。。。

很显然,先dfs跑一遍,再由深度浅的往根跳,枚举该点是否合法

那么一个一个往上跳吧?

看一看范围:500000!!!!

TLE的飞起

怎么优化呢?
倍增一下

往上一个成不成立?

不成立

2个呢?

4个呢?
终究会成立

时复大大下降

见代码:

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
struct ljb{
    int from,to;
}tu[];
],xyg[],n,m,root,sd[],f[][],have[],s,t;
float bz;
void read(int &x)
{
    ;
    x=;
    char s=getchar();
    ')
    {
        if(s=='-')
        {
            f=-;
        }
        s=getchar();
    }
    ')
    {
        x=x*+s-';
        s=getchar();
    }
    x*=f;
}
void shd(int u,int h)
{
    int ltt;
    sd[u]=h;
    ;i<=bz;i++)
    {
        <<i))
        {
            break;
        }
        f[u][i]=f[f[u][i-]][i-];
    }
    int k=head[u];
    )
    {
        ltt=tu[k].to;
        if(!have[ltt])
        {
            have[ltt]=;
            f[ltt][]=u;
            shd(ltt,h+);
        }
        k=xyg[k];
    }
}
int lca(int ltt,int kkk)
{
    int lzn=sd[ltt];
    int chen_ze=sd[kkk];
    if(lzn!=chen_ze)
    {
        if(lzn<chen_ze)
        {
            swap(ltt,kkk);
            swap(lzn,chen_ze);
        }
        int cha=lzn-chen_ze;
        ;i<=bz;i++)
        {
            <<i)&cha)
            {
                ltt=f[ltt][i];
            }
        }
    }
    if(ltt==kkk)
    {
        return kkk;
    }
    ;
    ;i--)
    {
        )
        {
            continue;
        }
        if(f[ltt][i]==f[kkk][i])
        {
            continue;
        }
        else
        {
            ltt=f[ltt][i];
            kkk=f[kkk][i];
        }
    }
    ];
}
int main()
{
    read(n);
    read(m);
    read(root);
    memset(head,-,sizeof(head));
    memset(xyg,-,sizeof(xyg));
    *(n-);
    ;i<=dsd;i+=)
    {
        read(s);
        read(t);
        tu[i].from=s;
        tu[i].to=t;
        tu[i+].from=t;
        tu[i+].to=s;
        xyg[i]=head[s];
        head[s]=i;
        xyg[i+]=head[t];
        head[t]=i+;
    }
    bz=log(n)/log()+;
    memset(have,,sizeof(have));
    memset(sd,,sizeof(sd));
    memset(f,-,sizeof(f));
    have[root]=;
    shd(root,);
    ;i<=n;i++)
    {
        ;j<=bz;j++)
        {
            <<j))
            {
                break;
            }
        }
    }
    ;i<=m;i++)
    {
        read(s);
        read(t);
        int y=lca(s,t);
        printf("%d\n",y);
    }
    ;
}

【模板】最近公共祖先(LCA)的更多相关文章

  1. [模板] 最近公共祖先/lca

    简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...

  2. Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)

    Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...

  3. POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)

    POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...

  4. POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)

    POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...

  5. 【lhyaaa】最近公共祖先LCA——倍增!!!

    高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...

  6. 最近公共祖先(LCA)模板

    以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...

  7. HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...

  8. luogu3379 【模板】最近公共祖先(LCA) 倍增法

    题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k( ...

  9. 最近公共祖先lca模板

    void dfs(int x,int root){//预处理fa和dep数组 fa[x][0]=root; dep[x]=dep[root]+1; for(int i=1;(1<<i)&l ...

  10. 【洛谷 p3379】模板-最近公共祖先(图论--倍增算法求LCA)

    题目:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 解法:倍增. 1 #include<cstdio> 2 #include<cstdlib> 3 #include ...

随机推荐

  1. iOS7 CookBook精彩瞬间(二)NSSet、通过Subscript访问类成员等

    1.NSSet的用法 ①NSSet是一种无序集合,基于hash实现,可以在线性时间复杂度内查找某个元素,如果要让元素有序,应当使用NSOrderedSet,要让集合可变,与NSArray类似,使用NS ...

  2. Android开发学习之路--Activity之初体验

    环境也搭建好了,android系统也基本了解了,那么接下来就可以开始学习android开发了,相信这么学下去肯定可以把android开发学习好的,再加上时而再温故下linux下的知识,看看androi ...

  3. 【Unity Shaders】Vertex & Fragment Shader入门

    写在前面 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface Shader中实现描边效果的弊端,也就是只对表面平缓的模型有效.这是因为我们是依赖法线和视角的点乘结果来进行描边判 ...

  4. 最简单的基于FFmpeg的内存读写的例子:内存播放器

    ===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章列表: 最简单的基于FFmpeg的内存读写的 ...

  5. Ubuntu 13.04设置root用户登录图形界面

    先切换到root用户, sudo su root 1.先设定一个root的密码, passwd root 2.备份一下lightgdm cp -p /etc/lightdm/lightdm.conf ...

  6. 深入浅出EF之ModelFirst和DBFirst

    在上篇博文中,小编主要简单的介绍了一下EF的一些基础知识,其中,小编蜻蜓点水的提了一下ModelFirst和DBFirst,ModelFirst先设计实体,然后根据模型生成数据库,DBFirst根据数 ...

  7. iOS中 GCD-Grand Central Dispath 多线程 UI_21

    GCD:Grand Central Dispath "牛逼的中枢调度器";是纯C语言编写的,提供了很多比较强大的函数 GCD:优势 1.目前是苹果主推的线程管理方式 2.它会自动的 ...

  8. 重载重写重定义-易混淆概念-C++编译器处理方式

    1.函数重载 1)必须在同一个类中进行. 2)子类无法重载父类的函数,父类同名函数将被名称覆盖 3)重载是在编译期间根据参数类型和个数决定函数调用 2.函数重写 1)必须发生于父类与子类之间 2)并且 ...

  9. Win10中virtualbox新建虚拟机不能设置64位系统解决

    问题描述 在Win10中,安装virtualBox后,新建虚拟电脑时,所有的操作系统都没有64位. 解决 进入控制面板->卸载程序->启用或关闭windows功能->取消hyper- ...

  10. UNIX环境高级编程——信号基本概述和signal函数

    一.为了理解信号,先从我们最熟悉的场景说起:1. 用户输入命令,在Shell下启动一个前台进程.2. 用户按下Ctrl-C,这个键盘输入产生一个硬件中断.3. 如果CPU当前正在执行这个进程的代码,则 ...