LCA倍增

想探讨一下lca问题的倍增解法

以洛谷第3379题为例

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
//建树邻接表;
int n,m,s,x,y,a,b,ans[500005];
int fir[500005],nex[500005],to[500005],tot,top;
int dep[500004],f[500005][22];
void build(int x,int y){
    to[++tot]=y;
    nex[tot]=fir[x];
    fir[x]=tot;
}
inline int read(){
  int X=0,w=0; char ch=0;
  while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
  while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
  return w?-X:X;
}
//预处理;
void deal_f(int u,int father){
    dep[u]=dep[father]+1;
    for(int i=0;i<=19;i++)
      f[u][i+1]=f[f[u][i]][i];//推出来的;
    for(int e=fir[u];e;e=nex[e]){
      int v=to[e];
      if(v==father) continue;//不处理,无意义;        
      f[v][0]=u;
      deal_f(v,u);//找寻相关子父点;
}
}
//LCA,自己仔细想一下;
int lac(int a,int b){
    if(dep[a]<dep[b]) swap(a,b);
    for(int i=20;i>=0;i--){
      if(dep[f[a][i]]>=dep[b]) a=f[a][i];//从上下调;
      if(a==b) return a;
}  
    for(int i=20;i>=0;i--){
     if(f[a][i]!=f[b][i]){
     a=f[a][i];
     b=f[b][i];
}
}
    return f[a][0];
}

int main(){
   scanf("%d%d%d",&n,&m,&s);
   for(int i=1;i<=n-1;i++){
     x=read();y=read();//scanf("%d%d",&x,&y);
     build(x,y);build(y,x);//无向图;
}
   deal_f(s,0);//因题中已确定根节点;
   for(int i=1;i<=m;i++){
     a=read();b=read();//scanf("%d%d",&a,&b);
     ans[i]=lac(a,b);
}
   for(int i=1;i<=m;i++){
     printf("%d\n",ans[i]);
}
}
假如用这个代码有三个点过不去。

究其原因是时间超限。

那么解决方法是(参考了大佬的解决方法,但在此具体提出,为我们这些有点晕的人

那就是你没注意数组的大小,我边打边写现在想哭3个小时就是因为数组开小了

将题中nex数组×2和to数组×2,即可;

第一次写有点水,见谅;

猜你喜欢

转载自www.cnblogs.com/WH-GR/p/11134591.html