zoukankan      html  css  js  c++  java
  • 对各种lca算法的理解

    1.RMQ+ST

      首先注意这个算法的要素:结点编号,dfs序,结点深度。

      首先dfs,求出dfs序,同时求出每个结点的深度。然后st算法,维护深度最小的结点编号(dfs序也可以,因为他们俩可以互相转换,只要不是深度就行了)。这样后面查询的时候才知道lca是哪个结点。如果维护的是深度。。那就不知道了。

      感觉这个算法的精髓在于:两个节点的dfs序间最小深度的结点一定是它们的lca(不会证)。至于结点编号和dfs序如何转换。。dfs序转换成结点编号很简单,数组取一下就行了。然而结点编号转换成dfs序需要对于每个结点存一个first,表示每个结点第一次在dfs序中出现的位置。为什么这样。。因为无论是维护还是查询,它和其他位置都还是一样的,没影响。

      所以只要认清三个要素,然后清楚它们如何转换就行了。

      时间复杂度。。预处理O(nlogn),查询O(1)吧。预处理上界紧。

    2.树剖

      树剖思想很好理解。。顺着链往上找就行了。注意两个结点同链时要取深度低的。

      时间复杂度:预处理O(n),查询O(logn)。上界都松。

    3.倍增

      倍增也就是先预处理一下,然后对于一个查询x,y,先把x,y跳到同一高度,再一起进退。。好理解吧。

      时间复杂度:预处理O(nlogn),查询O(logn)。上界紧。。(感觉这个好蒟蒻,但是好写)

    4.tarjan

      前面都是在线。。这个是秒杀一切的离线算法。

      它利用了dfs的性质。首先对于树dfs。当一个结点的一个孩子dfs完以后,再把它的孩子通过并查集并到它上面。注意不能按秩合并。。因为这个结点的孩子都遍历完以后,会查询与这个结点相关的询问。如果那个结点访问过,就查询那个结点的爸爸的爸爸的爸爸祖先,那一定是它们的lca。

      至于为什么不能立即合并,那是因为tarjan需要将子树独立,不然查询到的就是目前访问到的最低结点,而不是对于查询的lca了。

      时间复杂度:O(n)。上界。。紧不紧无关紧要。

    得出结论:如果数据不大的话,用好写的倍增。不然支持离线用tarjan,只能在线的话,查询多用RMQ+ST,节点多用树剖!

     

  • 相关阅读:
    使用IDEA创建SpringMVC项目
    Spring基于注解的配置——@Required、@Autowired、@Qualifier示例及与传统注入方法的对比
    Spring基于构造函数和设值函数的依赖注入
    Mysql——通配符和正则表达式的使用
    Spring Bean的生命周期、后置处理器、定义继承
    Spring Bean的定义及作用域
    MySql——使用where子句过滤数据
    MySql——创建数据表,查询数据,排序查询数据
    MySQL的安装+可视化工具+JDBC的增删改查
    slave_master_info和slave_relay_log_info中的Master_log_pos不一致
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/7460449.html
Copyright © 2011-2022 走看看