这道题为我的最近公共祖先问题开了个好头,纠结了好久才决定学习二分优化版的 lca,学完感觉还蛮简单的,直接附代码吧。
学习之前写的暴力法(70)
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+10;
vector<int>adj[N];
int n,m,s,u,v,ans;
int dfs(int fa,int id)
{
int res=0;
if(id==u||id==v) res++;
for(auto tem:adj[id])
{
if(tem==fa)continue;
if(dfs(id,tem))res++;
}
if(res==2) ans=id;
return res;
}
int main()
{
cin>>n>>m>>s;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
adj[x].push_back(y);
adj[y].push_back(x);
}
while(m--)
{
cin>>u>>v;
dfs(-1,s);
cout<<ans<<endl;
}
return 0;
}
学习了倍增法后:
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+10;
vector<int>adj[N];
int depth[N],fa[N][25],lg[N];
int n,m,s,x,y;
void init()
{
for(int i=1;i<=n;i++)
{
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
for(int i=1;i<=n;i++) lg[i]--;
}
void dfs(int fath,int u)
{
fa[u][0]=fath;
depth[u]=depth[fath]+1;
int d=depth[u];
for(int i=1;i<=lg[d];i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(auto v: adj[u])
{
if(v==fath)continue;
dfs(u,v);
}
}
int lca()
{
if(depth[x]<depth[y]) swap(x,y);
while(depth[x]>depth[y])
x=fa[x][lg[depth[x]-depth[y]]];
if(x==y) return x;
for(int i=lg[depth[x]];i>=0;i--)
{
if(fa[x][i]==fa[y][i])continue;
x=fa[x][i],y=fa[y][i];
}
return fa[x][0];
}
int main()
{
cin>>n>>m>>s;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
adj[x].push_back(y);
adj[y].push_back(x);
}
init();
dfs(0,s);
while(m--)
{
cin>>x>>y;
cout<<lca()<<endl;
}
return 0;
}