LCA

最近公共祖先LCA

定义

不想多说

倍增求LCA

定义 \(f[i][j]\) 数组含义为节点i向上走 \(2^j\) 后的节点是谁,也就是\(i\) 的第\(2^j\) 级祖先;

具体实现:

我们先把 \(dep\) 大的节点跳到与另一节点同一深度,如果跳完后\(x==y\) 直接返回x即可。

若不然,两个节点同时向上跳,注意需要跳到最近公共祖先的下一个节点,下一个节点的 \(2^0\) 级祖先

就是两个节点的LCA

\(f[i][j]\) 预处理 \(f[i][j] = f[f[i][j-1]][j-1]\)

int lca(int x,int y){
	if(dep[x] < dep[y]) swap(x,y);//找深度大的节点
	for(int i = 20; i >= 0; i--) if(dep[f[x][i]] >= dep[y]) x = f[x][i];//跳到同一深度
	if(x == y) return x;
	for(int i = 20; i >= 0; i--) if(f[x][i] != f[y][i]) x = f[x][i], y=f[y][i];//跳到lca的下一个节点
	return f[x][0];
}

树链剖分求LCA

预处理出 \(dep[i]\)\(top[i]\) ,\(top[i]\) 表示 \(i\) 所在重链 \(dep\) 最小的节点

设要求的两个节点为 \(x,y\) ,如果 \(x,y\) 在一条重链上,\(lca\) 就是 \(dep\) 小的的节点

如果不在一条重链上,那么我们需要每次使 \(dep\) 大的节点跳重链,

直到在一条重链上,\(x= fa[top[x]]\)

int lca(int x,int y){
   while(top[x]!=top[y]){
   	if(dep[top[x]]<dep[top[y]])swap(x,y);
   	x=fa[top[x]];//跳重链
   }
   return dep[x]<dep[y]?x:y;//选dep较小的
}
posted @ 2020-07-15 10:47  Aswert  阅读(144)  评论(1编辑  收藏  举报