LCA
倍增求LCA
错误的\(dfs\)
void dfs(int u,int fa){
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa)continue;
dfs(v,u);
}
for(int i=1;(1<<i)<=dep[u];++i){
f[u][i]=f[f[u][i-1]][i-1];
}
}
正确的\(dfs\)
void dfs(int u,int fa){
dep[u]=dep[fa]+1;
for(int i=1;(1<<i)<=dep[u];++i){
f[u][i]=f[f[u][i-1]][i-1];
}
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa){
continue;
}
f[v][0]=u;
dfs(v,u);
}
}
唯一的区别在于什么时候处理\(f\)数组,错误的码在叶子节点处理,但是显然叶子节点往上的节点都没有值,这样递推\(f\)中应该大部分都是错误的(然而在一些小数据中体现的不明显,所以我一直这么错还一直怀疑数据的锅)
倍增求LCA
\(O(\log n)\)
int Lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
int len=dep[u]-dep[v],k=0;
while(len){
if(len&1){
u=f[u][k];
}
len>>=1;k++;
}
if(u==v)return u;
for(int i=20;i>=0;--i){
if(f[u][i]!=f[v][i]){
u=f[u][i];
v=f[v][i];
}
}
return f[u][0];
}
另外还有ST表RMQ,树链剖分的求法,请到其他大佬的博客学习

浙公网安备 33010602011771号