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
\(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;
}