最近公共祖先(LCA)---朴素算法

假设目前求点u和v的最近公共祖先。
1、首先找到两点中深度较深的点(在树上的深度越深代表其越往下),不妨设深度较深的结点为u,不停的将u往上提,直到u的深度和v一样。
2、同时将u和v向上提,直到u

和v变成了同一个点。这个点就是要求的最近公共祖先。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int fa[N],d[N],n,m,rt;
vector<int>G[N];
void add(int u,int v)
{
 G[u].push_back(v);
 G[v].push_back(u);
 } 
void dfs(int u)//先计算每个点的深度
{
 for(int i = 0;i<G[u].size();i++)
 {
  int v = G[u][i];
  if(v==fa[u]) continue;
  fa[v]=u;//保存每个点的父节点 
  d[v]=d[u]+1;//子节点的深度比父节点多1
  dfs(v);
 }
 } 
 int LCA(int u,int v)
 {
  if(d[u]<d[v]) swap(u,v);//找出深度最深的点,保存在u中
  while(d[u]!=d[v]) u= fa[u];//先不停的让u变成它的父节点,往上提直到同一层
  while(u!=v)
  {
   u=fa[u];
   v=fa[v];
   //之后再不断地同时往上提u,v,直到它们相同之后,这个点就是答案
  }
  return u;
 }
 int main()
 {
  cin>>n>>m>>rt;
  for(int i = 1;i<n;i++)
  {
   int u,v;
   cin>>u>>v;
   add(u,v);
  }
  dfs(rt);
  for(int i = 1;i<=m;i++)
  {
   int u,v;
   cin>>u>>v;
   cout<<LCA(u,v)<<endl;
  }
 }


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值