Nearest Common Ancestors (LCA)

本文介绍了在数据结构中树的应用,并详细解释了最近公共祖先(LCA)的概念,通过示例说明了如何确定两个节点的LCA。文章提供了解题思路,包括倍增法求解LCA的步骤,以及预处理所需变量的定义。最后,给出了求解LCA问题的代码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据结构中的树,在计算机科学中是非常重要的,例如我们来看看下面这棵树:
在这里插入图片描述

在图中我们对每个节点都有编号了。 8号节点是这棵树的根。我们定义,一个子节点向它的根节点的路径上,任意一个节点都称为它的祖先。例如, 4号节点是16号节点的祖先。而10号节点同样也是16号的祖先。事实上,16号的祖先有8,4,10,16共四个。另外8, 4, 6,7都是7号节点的祖先,所以7号和16号的公共祖先是4和8号,而在这两个里面,4号是距离7和16最近的一个,所以我们称7号和16号的最近公共祖先是4号。

再例如,2和3的最近公共祖先是10,再例如6和13的是8。

现在你需要编写一个程序,在一棵树中找出指定两个节点的最近公共祖先

Input
第一行输入T表示有T组数据。每组第一行是N表示这棵树有多少个节点,其中 2<=N<=10,000。 节点用正整数1, 2,…, N表示。 接下来的 N -1 行表示这棵树的边,每行两个数,都是节点编号,前一个是后一个的父节点。最后一行是要查询的两个节点,计算出这两个节点的最近公共祖先
Output
对于每组测试输出一行,输出它们的最近公共祖先的编号。
Sample Input

2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5

Sample Output

4
3

解题思路:这个题就直接套LCA的板子就可以啦,我们先来讲一下LCA叭,
求LCA有三种方法(我知道的,可能有其他的,我太菜了,不知道),分别是并查集,RMQ,和倍增,这里我们来讲一下倍增,我们先介绍一下所需的变量。
lg[x]:表示2lg[x]是大于x的最小的数。
depth[x]:表示结点x在树中的深度。
f[u][i]:表示结点u的第2i位祖先。

倍增法的过程是:
1:先预处理出每个点的2的指数倍的祖先结点。
2:再寻找的时候,先让两个结点的深度相同,处理方法为找到较深的结点的与另一个结点相同深度的祖父结点。
3:此时如果是两个结点相同,那么答案就是本身,否则执行步骤4。
4:寻找两个结点中不相等的祖先结点,然后去寻找祖先结点的祖先结点,一直到找不到为止。

注意:在执行步骤4时,需要从最大的2的指数倍开始找,原因是:
如果从小开始找,比如LCA是结点的第17辈的祖先,
那么我们找就是 1+2+4+8=15,这个时候还差2才可以得到第17位,这里就要后悔,要返回前面的操作,而我们从大往小找的话:16+1=17,就只需要两步就得到答案啦。
代码:

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <bitset>
#include <queue>
//#include <random>
#include <time.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define ls root<<1
#define rs root<<1|1
const int maxn = 1e4 + 7;
//std::mt19937 rnd(time(NULL));
struct edge
{
    int v,next;
}e[maxn];
int cnt,head[maxn],f[maxn][20],depth[maxn],lg[maxn];
void add(int a,int b)
{
    e[++cnt]=edge{b,head[a]};
    head[a]=cnt;
}
void dfs(int u,int fa)
{
    f[u][0]=fa;
    depth[u]=depth[fa]+1;
    for(int i=1;(1<<i)<=depth[u];i++){
        f[u][i]=f[f[u][i-1]][i-1];
    }
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        dfs(v,u);
    }
}
int getlca(int a,int b)
{
    if(depth[a]<depth[b])swap(a,b);
    while(depth[a]>depth[b]){
        a=f[a][lg[depth[a]-depth[b]]-1];
    }
    if(a==b)return a;
    for(int i=lg[depth[a]]-1;i>=0;i--){
        if(f[a][i]!=f[b][i]){
            a=f[a][i],b=f[b][i];
        }
    }
    return f[a][0];
}
signed main()
{
    int t;
    scanf("%lld",&t);
    for(int i=1;i<maxn;i++){
        lg[i]=lg[i-1]+((1<<lg[i-1])==i);
    }
    while(t--){
        int n;
        scanf("%lld",&n);
        memset(head,0,sizeof head);
        cnt=0;
        int root=n;
        for(int i=1;i<n;i++){
            int a,b;
            root^=i;
            scanf("%lld%lld",&a,&b);
            root^=b;
            add(a,b);
        }
        dfs(root,0);
        int u,v;
        scanf("%lld%lld",&u,&v);
        printf("%lld\n",getlca(u,v));
    }
}

### Nearest Algorithm or Implementation in Programming In programming, the concept of 'nearest' is often associated with algorithms that deal with proximity or similarity between data points. One common application involves finding the nearest neighbor within a set of points based on some distance metric such as Euclidean distance. A widely used approach for this purpose includes **k-nearest neighbors (KNN)** which falls under supervised learning methods where it can be applied both to classification and regression tasks [^2]. For instance: - In classification problems using KNN, an object's class membership is determined by majority voting among its k closest training samples. Another relevant area could involve string matching techniques like Levenshtein Distance calculation when considering textual differences; however specific implementations depend heavily upon context including language choice etcetera but generally follow similar principles regarding measuring closeness/distance metrics appropriately adjusted according domain requirements whether numerical vectors spaces strings sequences et cetera . Here’s how you might implement basic version knn classifier python utilizing euclidian distances : ```python import numpy as np def classify_knn(data_points , query_point,k=3): """Classify new point via KNN.""" distances = [] for index,point in enumerate(data_points): dist=np.linalg.norm(np.array(point)-np.array(query_point)) distances.append((dist,index)) sorted_distances=sorted(distances,key=lambda x:x[0]) top_indices=[i for d,i in sorted_distances[:k]] classes=[data_points[i][1]for i in top_indices ] prediction=max(set(classes),key=classes.count) return prediction ``` This function takes list tuples form `(feature_vector,label)` pairs alongside single feature vector representing unknown sample whose category needs estimating through comparison against known instances stored inside `data_points`.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值