LCA模板

模板

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int MAX_N=501000;
vector<int>v[MAX_N];
int dp[MAX_N][20],dis[MAX_N],n,log_2[MAX_N];
void dfs(int now,int fa){
    int i;
    for(i=0;i<v[now].size();i++){
        int to=v[now][i];
        if(to==fa)
            continue;
        dp[to][0]=now;
        dis[to]=dis[now]+1;
        dfs(to,now);
    }
}
int LCA(int a,int b){
    int k=log_2[n],i;
    if(dis[a]<dis[b]){
        int c=a;
        a=b;
        b=c;
    }
    while(dis[a]!=dis[b]){
        for(i=k;i>=0;i--){
            if(dis[dp[a][i]]>=dis[b])
            a=dp[a][i];
        }
    }
    if(a==b){
        return b;
    }
    for(i=k;i>=0;i--){
        if(dp[a][i]!=dp[b][i]){
            a=dp[a][i];
            b=dp[b][i];
        }
    }
    return dp[a][0];
}
int main(void){
    int s,m,i,j,x,y;
    for(i=1;i<=500000;i++){
        log_2[i]=log_2[i-1]+(1<<log_2[i-1]==i);
    }
    scanf("%d%d%d",&n,&m,&s);
    for(i=0;i<n-1;i++){
        scanf("%d%d",&x,&y);
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(s,0);
    dis[0]=-1;
    for(i=1;i<=log_2[n];i++){
        for(j=1;j<=n;j++){
            dp[j][i]=dp[dp[j][i-1]][i-1];
        }
    }
    for(i=0;i<m;i++){
        scanf("%d%d",&x,&y);
        int pre=LCA(x,y);
        printf("%d\n",pre);
    }
    return 0;
}

用vector写的会T,o2优化才过的
改成邻接表应该就不会T了

P3379 【模板】最近公共祖先(LCA)

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
vector<int>edge[501000];
int dp[501000][20],have[501000],d[501000],N,log_2[501000];
void dfs(int now){
 int i;
 for(i=0;i<edge[now].size();i++){
  if(!have[edge[now][i]]){
   have[edge[now][i]]=1;
   dp[edge[now][i]][0]=now;
   d[edge[now][i]]=d[now]+1;
   dfs(edge[now][i]);
   have[edge[now][i]]=0;
  }
 }
}
int LCA(int a,int b){
 int k=log_2[N],i;
 if(d[a]<d[b]){
  int c=a;
  a=b;
  b=c;
 }
 while(d[a]!=d[b]){
  for(i=k;i>=0;i--){
   if(d[dp[a][i]]>=d[b])
   a=dp[a][i];
  }
 }
 if(a==b){
  return b;
 }
 for(i=k;i>=0;i--){
  if(dp[a][i]!=dp[b][i]){
   a=dp[a][i];
   b=dp[b][i];
  }
 }
 return dp[a][0];
}
int main(void){
 int M,S,i,j,u,v;
 scanf("%d%d%d",&N,&M,&S);
 for(i=1;i<=N;i++){
  log_2[i]=log_2[i-1]+(1<<log_2[i-1]==i);
 }
 for(i=0;i<N-1;i++){
  scanf("%d%d",&u,&v);
  edge[u].push_back(v);
  edge[v].push_back(u);
 }
 have[S]=1;
 dfs(S);
 d[0]=-1;
 for(i=1;i<=log_2[N];i++){
  for(j=1;j<=N;j++){
   dp[j][i]=dp[dp[j][i-1]][i-1];
  }
 }
 int a,b;
 for(i=0;i<M;i++){
  scanf("%d%d",&a,&b);
  int ans=LCA(a,b);
  printf("%d\n",ans);
 }
 return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值