LCA 倍增模板

感谢大佬模板,想要看更加精彩的讲解搓这里

构造访问数组:

void make_bin()
{
    bin[0]=1;
    for(int i=1;i<=15;i++)
        bin[i]=bin[i-1]<<1;
}

构造邻接表:

void Link()
{
    for(int i=1;i<=n-1;i++){//n-1 edges;or you can define a m pointing to the number of edges;
        scanf("%d%d",&u[i],&v[i]);
        //u[i+n-1]=v[i];v[i+n-1]=u[i];//双向; 
        next[i]=first[u[i]];
        //next[i+n-1]=first[v[i]];//双向;
        first[u[i]]=i;
        //first[v[i]]=i+n-1;//双向;
        isroot[v[i]]=true;
    }
}

宽搜:

void bfs()
{
    int head=0,tail=1;
    q[0]=root,vis[root]=true;
    while(head^tail){
        int now=q[head];head++;
        for(int i=1;i<=15;i++){
            if(bin[i]<=deep[now])
                fa[now][i]=fa[fa[now][i-1]][i-1];
            else break;
        }
        for(int i=first[now];i;i=next[i])
            if(!vis[v[i]]){
                vis[v[i]]=true;
                fa[v[i]][0]=now;
                deep[v[i]]=deep[now]+1;
                q[tail++]=v[i];
            }
    }
}

求lca:

int lca(int x,int y)
{
    if(deep[x]<deep[y])swap(x,y);
    int t=deep[x]-deep[y];
    for(int i=0;i<=15;i++)
        if(t&bin[i])x=fa[x][i];
    for(int i=15;i>=0;i--)
        if(fa[x][i]^fa[y][i])
            x=fa[x][i],y=fa[y][i];
    if(!(x^y))return y;
    return fa[x][0];
}

入门题:POJ1330
复杂度为 nlogn
题目代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define mst(x,y) memset(x,y,sizeof(x));
using namespace std;
const int maxn = 1e4+4;
int father[maxn][16];
int u[maxn],v[maxn];
int first[maxn],next[maxn],depth[maxn],q[maxn];
bool isroot[maxn];
int bin[16];
int n;
int root;
bool vis[maxn];
void make_bin(){
    bin[0] = 1;
    for(int i=1;i<=15;i++){
        bin[i] = bin[i-1]<<1;
    }
}
void link(){
    for(int i=1;i<n;i++){
        scanf("%d %d",&u[i],&v[i]);
        next[i] = first[u[i]];
        first[u[i]] = i;
        isroot[v[i]] = true;
    }
    for(int i=1;i<=n;i++){
        if(!isroot[i]){
            root = i;
            break;
        }
    }
}
void bfs(){
    int head = 0,tail = 1;
    q[0] = root;vis[root] = true;
    while(head^tail){
        int now = q[head];head++;
        for(int i=1;i<=15;i++){
            if(bin[i] < depth[now]){
                father[now][i] = father[father[now][i-1]][i-1];
            }else{
                break;
            }
        }
        for(int i=first[now];i;i=next[i]){
            if(!vis[v[i]]){
                vis[v[i]] = true;
                father[v[i]][0] = now;
                depth[v[i]] = depth[now]+1;
                q[tail++] = v[i];
            }
        }
    }
}
int lca(int x,int y){
    if(depth[x] < depth[y]){
        swap(x,y);
    }
    int t = depth[x]  - depth[y];
    for(int i=0;i<=15;i++){
        if(t&bin[i]) x = father[x][i];
    }
    for(int i=15;i>=0;i--){
        if(father[x][i]^father[y][i]){
            x=father[x][i];y=father[y][i];
        }
    }
    if(!(x^y)) return y;
    return father[x][0];
}
void init(){
    mst(vis,false);
    mst(isroot,false);
    mst(u,0);
    mst(v,0);
    mst(first,0);
    mst(next,0);
    mst(father,0);
    mst(depth,0);
    mst(q,0);
}
int main(){
    int t;
    make_bin();
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d",&n);
        link();
        bfs();
        int x,y;
        scanf("%d %d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值