//悲观者永远正确,乐观者永远前行。|

ccrui

园龄:2年2个月粉丝:2关注:4

LCA学习笔记


LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。

实现

暴力

O(nm)

不说了。

int query(Node t, Node u, Node v) {
int left=u.value;
int right=v.value;
//如果左结点大于右结点则交换
if(left>right)swap(left,right);
while(1){
//如果t小于u、v则往t的右子树中查找
if(t.value<left)t=t.right;//如果t大于u、v则往t的左子树中查找
else if(t.value>right)t=t.left;
else return t.value;
}
}

Tarjan

详见Tarjan处

O(n+m)

并查集维护祖先。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,s;
struct ask{
int a,b;
};
vector<ask>quer[1000100];
vector<int>v[1000100];
int fa[1000001],k[1000001],d[10000001],ans[10000001];
int find(int x){
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]);
}
void tarjan(int x){
k[x]=1;
for(auto i:v[x]){
if(k[i])continue;
d[i]=d[x]+1;
tarjan(i);
fa[i]=x;
}
for(int i=0;i<quer[x].size();i++){
int y=quer[x][i].a,id=quer[x][i].b;
if(k[y]==2){
int lca=find(y);
ans[id]=lca;
}
}
k[x]=2;
}
signed main(){
cin>>n>>m>>s;
for(int i=0;i<=n;i++)fa[i]=i;
for(int i=1;i<n;i++){
int uu,vv;
cin>>uu>>vv;
v[uu].push_back(vv);
v[vv].push_back(uu);
}
for(int i=1;i<=m;i++){
int uu,vv;
cin>>uu>>vv;
if(uu==vv)ans[i]=uu;
quer[uu].push_back(ask{vv,i});
quer[vv].push_back(ask{uu,i});
}
tarjan(s);
for(int i=1;i<=m;i++){
cout<<ans[i]<<endl;
}
return 0;
}

倍增

树链剖分

本文作者:ccrui

本文链接:https://www.cnblogs.com/ccr-note/p/LCA-note.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ccrui  阅读(15)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示