zoukankan      html  css  js  c++  java
  • 倍增 tarjan求lca

    对于每个节点v,记录anc[v][k],表示从它向上走2k步后到达的节点(如果越过了根节点,那么anc[v][k]就是根节点)。

    dfs函数对树进行的dfs,先求出anc[v][0],再利用anc[v][k] = anc[anc[v][k - 1]][k - 1]  (从v向上2k步即为从v向上2(k - 1)步再向上2(k - 1)步)

    求出其他anc[v][k]的值

    lca(u, v)函数寻找u和v的lca, 首先把u和v调整到一个高度。如果此时u和v重合,那么这就是我们要找的lca,如果他们补充和,就不断的寻找一个最小的k,使得

    anc[u][k] = anc[v][k]

    int anc[maxn][20], deep[maxn];
    
    int dfs(int u, int fa)
    {
        for(int i = 1; i < 20; i++)
            anc[u][i] = anc[anc[u][i - 1]][i - 1];
        for(int i = head2[u]; i != -1; i = Edge[i].next)
        {
            int v = Edge[i].v;
            if(v == fa || deep[v]) continue;
            anc[v][0] = u;
            deep[v] = deep[u] + 1;
            dfs(v, u);
        }
    }
    
    int lca(int u, int v)
    {
        if(deep[u] < deep[v]) swap(u, v);
        for(int i = 20 - 1; i >= 0; i--)
            if(deep[anc[u][i]] >= deep[v])
                u = anc[u][i];
    
        for(int i = 20 - 1; i >= 0; i--)
        {
            if(anc[u][i] != anc[v][i])
            {
                u = anc[u][i];
                v = anc[v][i];
            }
        }
        if(u == v) return u;
        return anc[u][0];
    }

    tarjan求lca  

    1.任选一个点为根节点,从根节点开始。

    2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。

    3.若是v还有子节点,返回2,否则下一步。

    4.合并v到u上。

    5.寻找与当前点u有询问关系的点v。

    合并就用并查集就好了

    板子先欠着

          6.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。

    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    XTU1199:Number Game
    SSL连接建立过程分析(1)
    JavaScript高级编程II
    PreferenceFragment 使用 小结
    crm使用soap更改下拉框的文本值
    POJ2241——The Tower of Babylon
    四个好看的CSS样式表格
    无论你在哪里上班,请记住下面黄金法则!
    js的for in循环和java里的foreach循环的差别
    具体解释EBS接口开发之物料导入API
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/10731860.html
Copyright © 2011-2022 走看看