因为学的比较浅,直接上模板,有不足的地方请指正·-·!

既然要学LCA,那我们要明白LCA,是怎么定义的,怎么确定哪个是LCA。 LCA 被称为 最近公共祖先。 下面只介绍一种方法——倍增法【我不会说我只学了一种的】 。


先写个大致的思路:接下来是按照这样的思路放模板。首先脑海里浮想出一棵树,然后节点u,v。OK , 可以开始放模板了。这题输入针对,可以一边看那题一边看模板,可能会好理解一点传送门

for(int i=2;i<=n;i++) //G是一个滚动数组vector <int> G[maxn];这里的i只针对文章分类LCA中的第一篇。这段代码的要求是建树(也就是浮想出一棵树的实现)
    {
        int t;
        scanf("%d",&t);
        G[i].push_back(t);// 建立两个节点,无向图的关系。其实就是儿子和父亲的关系。
        G[t].push_back(i);
    }
建完图,开始对图进行初始化处理。处理出 各点的深度。

void dfs(int v,int p,int d)//par[i][j]代表第j个点,向上走2^i次对应的节点
{
    par[0][v]=p;
    dep[v]=d;
    for(int i=0;i<G[v].size();i++)
        if(G[v][i]!=p)  dfs(G[v][i],v,d+1); // G[v][i]!=p是为了防止回溯。
    return ;
}
void init()
{
    dfs(root,-1,0);// dfs跑一遍图,处理深度
    for(int k=0;k<maxlog;k++) //   maxlog=ceil(log2(n))  n代表节点数,原因的话可以画一下图就可以知道是为什么了
        for(int v=1;v<=n;v++) // 枚举所有的节点1-n
            par[k+1][v]= par[k][v]<0 ? -1:par[k][par[k][v]];
对于顶点v , 向上走两步的节点是par[par[v]].走4步的节点是par2[par[2]]。因此,向上走2^k次对应的顶点就是par[k][v].
<0的情况就是根节点往上走,因为走不上去,所有都是-1。
    return ;
}
接下来有上面关于     点的深度,以及点走2^k步会走到哪个节点    的信息。 我们可以求LCA了。

int lca(int u,int v)
{
    if(dep[u]>dep[v])   swap(u,v); // 使得v是深度最大的节点。
    for(int k=0;k<maxlog;k++) // 目的是让u,v的深度相同。原因:相同了之后,再往上找第一个公共的点,那就是LCA了。
        if((dep[v]-dep[u])>>k & 1) // 意思是  delta(dep)/(2^k)后的值 mod2 。如果为1,那么要往上走2^k次步;否则不动。
            v=par[k][v];
    if(u==v)    return u;// 这里是为了防止同一条线两点重合的情况。如果不特判的话,return 的就是u的father了。结果就会出错
    for(int k=maxlog-1;k>=0;k--)
        if(par[k][u]!=par[k][v])    u=par[k][u],v=par[k][v];
    return par[0][u];
}

好了,这就是所有的模板了。
现在碰到LCA的题仅有一题:模型是,求两个点到确定点的最短路的 公共点有多少个