带查询的节点为x和y节点,书的深度为d
倍增法
预处理f[i][j]时间复杂度:nlog(n) 查询O(logn)
倍增法(bfs)代码
int fa[N][16],depth[N];
int q[N],hh = 0,tt = 0;
int head[N],cnt;
struct Edge{
int v,next;
}edge[M];
void add(int u,int v){
edge[cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt ++;
}
void bfs(int root){
//预处理
memset(depth,INF,sizeof depth);
q[0] = root;
depth[0] = 0;
depth[root] = 1,fa[root][0] = 0;
while(hh <= tt){
int t = q[hh ++];
for(int i = head[t];~i;i = edge[i].next){
int ver = edge[i].v;
if(depth[ver] < depth[t] + 1)continue;
depth[ver] = depth[t] + 1;
q[++ tt] = ver;
fa[ver][0] = t;
for(int k = 1;k < 16;k ++){
fa[ver][k] = fa[fa[ver][k - 1]][k - 1];
}
}
}
}
int lca(int a,int b){
if(depth[a] < depth[b])swap(a,b);
for(int k = 15;k >= 0;k --)
if(depth[fa[a][k]] >= depth[b])
a = fa[a][k];
if(a == b)return a;
for(int k = 15;k >= 0;k --)
if(fa[a][k] != fa[b][k]){
a = fa[a][k];
b = fa[b][k];
}
return fa[a][0];
}Tarjan
struct Edge{
int v,next;
}edge[M];
void add(int u,int v){
edge[cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt ++;
}
void init(){
for(int i = 0;i < N;i ++)fa[i] = i;
}
int Find(int x){
return fa[x] = (fa[x] == x ? x : Find(fa[x]));
}
void Tarjan(int u,int f){
vis[u] = true;
for(auto &q : query[u]){
int y = q.x,id = q.y;
if(vis[y])res[id] = Find(y); //如果之前遍历过另一个节点
}
for(int i = head[u];~i;i = edge[i].next){
int ver = edge[i].v;
if(ver == f)continue;
Tarjan(ver,u);
fa[ver] = u;
}
}发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168771.html原文链接:https://javaforall.cn