• LCA算法,正常迭代实现与tarjan离线实现


    lca算法是用于在一个树或者一个图中,找出两个节点的公共祖先的算法。

    有什么用呢?举一个例子:在一棵树上,当我们随便添加一条边的时候,那么就会在原来的树上形成环。如何把这个环找出来呢?嘿嘿,lca算法便是了!

    lca算法是运用需要一个预热的过程,简单的说,就是他需要一棵树或者一个图中节点的每个点的深度和父节点。

    呵呵,简单啊,DFS就是了。

    接下来根据已知的信息,不断的将两个节点往回迭代,直到找到了同一高度,同一个父节点。这个节点便是他们两点的公共祖先了,而这个过程经过的边加起来,便是我们要找的环!

    1、DFS(略)
    
    2、
    
    Int  lca(int u,int v) //lca算法,在某一个图中,找出u,v的公共祖先
    
    {
    
             if(h[u]>h[v]) // 深度不同,单个节点向上攀爬,到与另一节点同一高度
    
             {
    
                       while(h[u]>h[v]) //提示:在这个循环里做文章,就可以解决很多环的问题
    
                       {
    
                                u=pre[u];
    
                       }
    
             }
    
             else if(h[v]>h[u])
    
             {
    
                       while(h[v]>h[u])
    
                       {
    
                                v=pre[v];
    
                       }
    
             }
    
             while(u!=v)  //深度相同了,同时向上攀爬,直到成了同一点
    
             {
    
                       u=pre[u];
    
                       v=pre[v];
    
             }
    
    return  u; //找到了公共祖先
    
    }
    
    

     

     

    下面是tarjan离线算法实现LCA

    自己看的,不好意思

    int find(int x) //并查集
    {
    	if(x!=pre[x])
    	{
    		pre[x]=find(pre[x]); //路径压缩
    	}
    	return pre[x];
    }
    
    int lca(int u,int f) //当前节点,父节点
    {
    	pre[u]=u;  //设立当前节点的集合 
    	for(node *p=link[u];p;p=p->next)
    	{
    		if(p->v==f)
    			continue;
    		lca(p->v,u);  //搜索子树
    		pre[p->v]=u; //合并子树
    	}
    	v[u]=1; //以u点为集合的点搜索完毕
    	if(u==A && v[B]==1)
    	{
    		printf("%d\n",pre[find(B)]);
    	}
    	else if(u==B && v[A]==1)
    	{
    		printf("%d\n",pre[find(A)]);
    	}
    	return 0;
    }
    

     

    Tarjan算法基于深度优先搜索的框架,对于新搜索到的一个结点,首先创建由这个结点构成的集合,再对当前结点的每一个子树进行搜索,每搜索完一棵子树,则可确定子树内的LCA询问都已解决。其他的LCA询问的结果必然在这个子树之外,这时把子树所形成的集合与当前结点的集合合并,并将当前结点设为这个集合的祖先。之后继续搜索下一棵子树,直到当前结点的所有子树搜索完。这时把当前结点也设为已被检查过的,同时可以处理有关当前结点的LCA询问,如果有一个从当前结点到结点v的询问,且v已被检查过,则由于进行的是深度优先搜索,当前结点与v的最近公共祖先一定还没有被检查,而这个最近公共祖先的包涵v的子树一定已经搜索过了,那么这个最近公共祖先一定是v所在集合的祖先。

  • 相关阅读:
    Java作业十(2017-11-8)
    Java作业九(2017-11-6)
    Java作业八(2017-10-30)
    Java作业七(2017-10-30)
    Java作业六(2017-10-30)
    Java作业五(2017-10-15)
    如何获取jqGrid中选择的行的数据
    如何修改WAMP中mysql默认空密码
    为 PhpStorm 配置 Xdebug 来调试代码
    MySQL load_file()/into outfile路径问题总结
  • 原文地址:https://www.cnblogs.com/ka200812/p/2124984.html
Copyright © 2020-2023  润新知