• lca tarjin


    这个算法  我个人认为是  遍历每一个点把它当成一些询问的最近祖先

            1

          2    3

        4     5  6

    low是并差集,vis是是否访问过,访问过为true,没有为false;

    假设询问是(4,4),(4,5),(2,6),(3,6)

    按程序最先递归到4点,之后4没有了后继节点,

    vis[4] = true;

    证明4已经访问过了,然后就开始遍历4的询问,发现4有两个询问,第一个是(4,4),现在4是true,

    那么就是说4是到过的点,然后我们就find祖先,因为没有点进行low数组的更新(就是当前节点low值没有指向父节点),意味着父祖先卡死在了4这个点,输出4

    然后发现(4,5)也是一个询问,但是明显vis[5] = false;那么就不进行查找

    回到2点,跟新low[4] = 2,然后发现

    2除了4,没有后继节点,

    vis[2]  =true;

    有一个询问(2,6)但是vis[6] = false;所以不find。

    然后回到1,跟新  low[2] = 1;

    进入右边的3,又进入了右边的5,没有后继节点,

    之后看询问,发现有一个询问就是我们没有处理的(4,5),这时候发现vis[4] = true于是find(4) == 1

    回到3点,跟新low值low[5] = 3;

    进入6点

    进入6发现

    6点没有子节点,

    vis[6] = true

    有一个2,6询问,这时2,6都是true之后find(2) == 1,

    有一个(3,6)询问,但是3是false,不询问,返回3点

    返回3点

    low[6] = 3;

    3点走完了子节点

    vis[3] = true;

    有一个(3,6)询问,vis[3] && vis[6]  所以find(6) == 3

    3走完了返回1

    返回1,low[3] = 1

    子节点走完了

    vis[1] = true;

    没有询问

    程序结束

    bb这么多,画一遍图就明白了,我觉得这个东西像一个树的合并,每次返回到上一层都是一次合并,就像(4,5)的询问一样,

    我认为这时候是1的左子树和右子树进行了合并,而我们递归是一层层向上返回的,所以找到的第一个点就是合并的那个点

    这个东西我个感觉为和tarjin算法关系不是很大,但是网上很多求法都说lca用tarjin算法,我估计还是我这个对tarjin算法的理解不够到位,

    要是那里说的不对,还是请多指点一下

    void lca(int u)

    {

        int i,j;

        vis[u] = true;

        for(i = 0;i < pp[u].size(); ++i)

        {

            j = pp[u][i];

            if(vis[j] == true)

                cout << findx(u) << endl;

        }

        for(i = 0; i < p[u].size(); ++i)

        {

            j = p[u][i];

            lca(j);

            low[j] = u;

        }

    }

    int findx(int x)

    {

        if(x == low[x])

            return x;

        return low[x];

    }

  • 相关阅读:
    update语句中存在''语法书写方式
    CSS的代码风格
    CSS的语法规范
    CSS层叠样式表导读
    CSS简介
    HTML基本标签(下)
    HTML基本标签(上)
    HTML简介导读
    集合及其运用
    字典的镶嵌
  • 原文地址:https://www.cnblogs.com/mltang/p/7815869.html
Copyright © 2020-2023  润新知