Company Queries II
/*
Company Queries II
https://cses.fi/problemset/task/1688/
这题就是求lca的模板题
下面代码用倍增法
*/
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
vector<int> g[N];
int fa[N][20], d[N];
int n,q,a,b;
void dfs(int x, int f){
d[x]=d[f]+1; fa[x][0]=f;
// cout<<x<<" depth: "<<d[x]<<endl;
for(auto y: g[x]){
if(y!=f)
dfs(y, x);
}
}
/*
先将 $a$ 和 $b$ 中较低的节点提升到与另一个节点相同的深度。
然后,我们将这两个节点依次递减地向上提升。最后,任一节点的父节点就是这两个节点的 LCA。
*/
int lca(int x, int y){
if(d[x]<d[y]) swap(x, y);
int k=d[x]-d[y];
for(int i=19;i>=0;i--){
if((k>>i)&1) x=fa[x][i];
}
if(x==y) return y;
for(int i=19;i>=0;i--){
if(fa[x][i]!=fa[y][i])
x=fa[x][i], y=fa[y][i];
}
return fa[x][0];
}
int main()
{
cin>>n>>q;
for(int i=2;i<=n;i++){
int t;
cin>>t;
g[t].push_back(i);
g[i].push_back(t);
}
dfs(1, 0);
for(int k=1;k<20;k++)
for(int i=1;i<=n;i++)
{
int m=fa[i][k-1];
fa[i][k]=fa[m][k-1];
// cout<<i<<" "<<k<<" fa:"<<fa[i][k]<<endl;
}
while(q--){
cin>>a>>b;
cout<<lca(a, b)<<'\n';
}
return 0;
}
欧拉序做法:
/*
Company Queries II
https://cses.fi/problemset/task/1688/
这题就是求lca的模板题
用欧拉序处理
*/
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
vector<int> g[N];
int fa[N][20], d[N];
int n,q,a,b;
int timer, tin[N], tout[N];//记录进入和出来的时间
void dfs(int x, int f){
fa[x][0]=f;
tin[x]=++timer;
// cout<<"tin "<<x<<": timer "<<tin[x]<<endl;
// cout<<x<<" depth: "<<d[x]<<endl;
for(auto y: g[x]){
if(y!=f)
dfs(y, x);
}
tout[x]=timer;
// cout<<"tout "<<x<<": timer "<<tout[x]<<endl;
}
//判断 x 是否是 y 的祖先
bool is_ancestor(int x, int y){
return tin[x]<=tin[y] && tout[x]>=tout[y];
}
/*
1、先判断是否有祖先关系,有的话,直接返回
2、否则,类似倍增, 我们将这其中一个节点依次递减地向上提升
*/
int lca(int x, int y){
if(is_ancestor(x, y)) return x;
if(is_ancestor(y, x)) return y;
for(int i=19;i>=0;i--){
if(fa[x][i] && !is_ancestor(fa[x][i], y)) //如果不是0号结点,且不是祖先
x=fa[x][i];//往上跳
}
return fa[x][0]; //最后x的父亲必定是x与y的LCA
}
int main()
{
cin>>n>>q;
for(int i=2;i<=n;i++){
int t;
cin>>t;
g[t].push_back(i);
g[i].push_back(t);
}
dfs(1, 0);
for(int k=1;k<20;k++)
for(int i=1;i<=n;i++)
{
int m=fa[i][k-1];
fa[i][k]=fa[m][k-1];
// cout<<i<<" "<<k<<" fa:"<<fa[i][k]<<endl;
}
while(q--){
cin>>a>>b;
cout<<lca(a, b)<<'\n';
}
return 0;
}

浙公网安备 33010602011771号