tarjan,树剖,倍增求lca

Posted asdic

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tarjan,树剖,倍增求lca相关的知识,希望对你有一定的参考价值。

1.tarjan求lca

 Tarjan(u)//marge和find为并查集合并函数和查找函数
{
        for each(u,v)    //访问所有u子节点v
      {
        Tarjan(v);        //继续往下遍历
        marge(u,v);    //合并v到u上
        标记v被访问过;
        }
        for each(u,e)    //访问所有和u有询问关系的e
       {
          如果e被访问过;
          u,e的最近公共祖先为find(e);
       }
}

2.倍增lca(在线)

#include<bits/stdc++.h>

using namespace std;

const int N=100000;
const int M=1000000;

int dep[N],fa[N][20];

int head[N],tot;
struct node{int v,next;}e[N];
void insert(int u,int v){
    e[++tot]=(node){v,head[u]};head[u]=tot;}

void dfs(int u,int f){
    dep[u]=dep[f]+1;
    fa[u]=f;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        dfs(v,u);}
}

int lca(int x,int y){
    int i,j;
    if(dep[x]<dep[y]) swap(x,y);
    
    for(i=0;(1<<i)<=dep[x];i++);
    --i;
    
    for(j=i;j>=0;j--)
    if(dep[x]-(1<<j)>=dep[y])
    x=fa[x][j];
    
    if(x==y) return x;
    
    for(j=i;j>=0;j--)
    if(fa[x][j]!=fa[y][j])
    x=fa[x][j],y=fa[y][j];
    
    return fa[x][0];}


int main(){
    int n;cin>>n;
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        insert(u,v);insert(v,u);}
    
    dfs(1,0);
     
    for(int j=1;(1<<j)<=n;j++)
    for(int i=1;i<=n;i++)
    fa[i][j]=fa[fa[i][j-1]][j-1];
    
    int q;
    cin>>q;
    while(q--){
        int a,b;cin>>a>>b;
        cout<<lca(a,b)<<endl;
    }return 0;
}

3.树剖lca(在线)

void dfs1(int u,int f){
    dep[u]=dep[f]+1;
    siz[u]=1;
    fa[u]=f;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(v==f) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[son[u]]<siz[v]) son[u]=v;}}

void dfs2(int u,int tp){
    top[u]=tp;   // top就是当前所在链的顶端
    if(!son[u]) return;
    dfs2(son[u],tp);
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(!top[v]) dfs2(v,v);}}
        
int lca(int x,int y){
    int fx=top[x],fy=top[y];//将x,y放到同一重链上
    while(fx!=fy){
        if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
        x=fa[fx],fx=top[x];}
    return dep[u]<dep[v]?u:v;}//选取深度小的输出

 

以上是关于tarjan,树剖,倍增求lca的主要内容,如果未能解决你的问题,请参考以下文章

lca

51nod2621 树上距离一题四解ST表+倍增+Tarjan+树剖

倍增 Tarjan 求LCA

两种lca的求法:树上倍增,tarjan

最近在写一些树上的东西,先发一波LCA的吧!

Tarjan求LCA