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

倍增

树链剖分

posted @ 2023-08-17 15:05  ccrui  阅读(22)  评论(0)    收藏  举报