• LCA---Tarjan算法


           本问题中Tarjan算法不需要设置栈和dfn,low标号,而是设置了并查集。

             通过一次dfs遍历即可找出所有节点对的lca。将这样一次读取所有查询,计算一次后返回所有查询lca的算法称为离线算法 

             涉及到在线算法和离线算法这两个概念的算法还有区域最值查询问题(RMQ问题)。

          以下方法均可用于有向图【先查找出根节点root,再DFS】和无向图【root可以任意设置或者是直接遍历所有节点】

          原图和询问可以存储为【链式向前型】和【邻接表】的形式,注意定义形式即可。

    【1】使用union函数

     1 void LCA_Tarjan(int u)
     2 {
     3     int now_to;
     4     int i;
     5 
     6     vis[u]=1;   //标记+访问+遍历
     7     ancestor[u]=u;
     8     for(i=Tnode[u].pre;i!=-1;i=Tedge[i].pre)
     9     {
    10         now_to=Tedge[i].to_vertex;
    11         if(!vis[now_to])
    12         {
    13             LCA_Tarjan(now_to);
    14             Union(u,now_to);
    15                 ancestor[Find(now_to)]=u;  //ancestor[Find(u)]=u;  效果一样
    16         }
    17     }
    18     for(i=Qnode[u].pre;i!=-1;i=Qedge[i].pre)
    19     {
    20         now_to=Qedge[i].to_vertex;
    21         if(vis[now_to])
    22         {
    23             lca[Qedge[i].num]=ancestor[Find(now_to)]; //单独开数组存储
    24                  //     Qedge[2*Qedge[i].num-1].ans=Qedge[2*Qedge[i].num].ans=ancestor[Find(now_to)];
    25         }
    26     }
    27 }

    【2】不使用union函数

     1 void LCA_Tarjan(int u)
     2 { 
     3     int now_to;   
     4     int i; 
     5     
     6     vis[u]=1;  //标记+访问+遍历
     7     f[u]=u;   //将其父亲(根)指向自己
     8     for(i=Tnode[u].pre;i!=-1;i=Tedge[i].pre) /
     9     {
    10         now_to=Tedge[i].to_vertex;
    11         if(!vis[now_to])
    12         {
    13             LCA_Tarjan(now_to);
    14             f[now_to]=u;  //存储当前最近公共祖先
    15         }
    16     }
    17 
    18     for(i=Qnode[u].pre;i!=-1;i=Qedge[i].pre)  
    19     {
    20         now_to=Qedge[i].to_vertex;
    21         if(vis[now_to])  //如果其子节点及子节点的子树全部访问完才会进入这一步,由vis判断
    22         {                //如果已经访问了问题节点,就可以返回结果
    23                     lca[Qedge[i].num]=Find(now_to);
    24                    //    Qedge[2*Qedge[i].num-1].ans=Qedge[2*Qedge[i].num].ans=Find(now_to);  /*均可*/
    25         }
    26     }
    27 }
    ---  纵使山重水复,亦会柳暗花明   sunqh1991@163.com   欢迎关注,互相交流
  • 相关阅读:
    vue 组件复用不刷新
    ES6删除对象中的某个元素
    UI组件--element-ui--Table组件自定义合计行
    UI组件--element-ui合计行在横向滚动条下面的解决方法
    java笔记 -- 数组
    java笔记 -- 输入输出
    java笔记 -- java字符串
    java笔记 -- 数学函数与常量
    java笔记 -- java运算
    java笔记 -- java变量与常量的声明
  • 原文地址:https://www.cnblogs.com/wjcx-sqh/p/5929922.html
Copyright © 2020-2023  润新知