LCA模板
倍增
时间复杂度 \(O(n\log n)\)。
代码
#include<bits/stdc++.h>
using namespace std;
int anc[500010][21];//anc[i][j]表示i节点的2^j级祖先
int n,m,s;
int d[500010];//d数组表示当前节点的深度
vector<int> p[500010];
void dfs(int u,int fa){
for(int i=0;i<p[u].size();i++){
int v=p[u][i];
if(v==fa) continue;
d[v]=d[u]+1;//子节点的深度是父节点+1
anc[v][0]=u;//子节点的2^0级节点是父节点
dfs(v,u);
}
}
void init(){
for(int j=1;j<=18;j++)//根据题目更改
for(int i=1;i<=n;i++)
anc[i][j]=anc[anc[i][j-1]][j-1];
}
int LCA(int u,int v){
if(d[u]<d[v]) swap(u,v);//将u当做深度较深的节点
for(int i=18;i>=0;i--)
if(d[anc[u][i]]>=d[v])
u=anc[u][i];//枚举二进制将u往上提
if(u==v) return u;
for(int i=18;i>=0;i--)
if(anc[u][i]!=anc[v][i])
u=anc[u][i],v=anc[v][i];//用同样的方法提两个节点,直到相同
return anc[u][0];
}
int main(){
cin>>n>>m>>s;
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
p[u].push_back(v);
p[v].push_back(u);
}
d[s]=1,dfs(s,0);
init();
while(m--){
int u,v;
cin>>u>>v;
cout<<LCA(u,v)<<'\n';
}
return 0;
}
Tarjan
时间复杂度 \(O(n+m)\)。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{int u,id;};
int n,m,s;
vector<int> p[500010];
vector<node> Q[500010];
int fa[500010];
bool vis[500010];
int ans[500010];
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}//并查集
void Tarjan(int u){
fa[u]=u;
vis[u]=1;
for(int i=0;i<p[u].size();i++){
int v=p[u][i];
if(vis[v]) continue;
Tarjan(v);
fa[v]=u;
}
for(int i=0;i<Q[u].size();i++){
node v=Q[u][i];
if(!vis[v.u]) continue;
ans[v.id]=find(v.u);
}
}
signed main(){
cin>>n>>m>>s;
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
p[u].push_back(v);
p[v].push_back(u);
}
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
Q[u].push_back({v,i});
Q[v].push_back({u,i});
}
Tarjan(s);
for(int i=1;i<=m;i++) cout<<ans[i]<<'\n';
return 0;
}

浙公网安备 33010602011771号