LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。

Tarjan是一种离线算法,时间复杂度O(n+Q),Q表示询问次数,其中使用倍增法加速算法。

首先dfs建立二叉树,并标记深度、父节点。

在LCA函数中,交换x、y保证x深度最大,计算深度差,在进行有限次计算后,保持x、y深度一致,再次进行多次倍增,寻找到最近公共祖先

最后计算节点距离差:deep[x]+deep[y]-deep[t]*2

 #include<iostream>
#include<cstdio>
using namespace std; const int MAXN=;
struct Edge
{
int to,next;
}E[MAXN];
int node,head[MAXN];
int deep[MAXN],fa[MAXN][];
bool vis[MAXN];
int n,m,ans;
int a[MAXN]; void insert(int u,int v)
{
E[++node]=(Edge){v,head[u]};head[u]=node;
E[++node]=(Edge){u,head[v]};head[v]=node;
} void dfs(int x)
{
vis[x]=;
for(int i=;i<=;i++)
{
if(deep[x]<(<<i)) break;
fa[x][i]=fa[fa[x][i-]][i-];
}
for(int i=head[x];i;i=E[i].next)
{
if(vis[E[i].to]) continue;
deep[E[i].to]=deep[x]+;
fa[E[i].to][]=x;
dfs(E[i].to);
}
} int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
int d=deep[x]-deep[y];
for(int i=;i<=;i++)
if((<<i)&d) x=fa[x][i];
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
if(x==y) return x;
else return fa[x][];
} int dis(int x,int y)
{
int t=lca(x,y);
return deep[x]+deep[y]-deep[t]*;
} int main()
{
scanf("%d",&n);
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
}
dfs();
scanf("%d",&m);
for(int i=;i<=m;i++)
scanf("%d",&a[i]);
for(int i=;i<m;i++)
ans+=dis(a[i],a[i+]);
printf("%d",ans);
return ;
}

LCA最近公共祖先——Tarjan模板的更多相关文章

  1. LCA 最近公共祖先 tarjan离线 总结 结合3个例题

    在网上找了一些对tarjan算法解释较好的文章 并加入了自己的理解 LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通 ...

  2. lca最近公共祖先(模板)

    洛谷上的lca模板题--传送门 学了求lca的tarjan算法(离线),在洛谷上做模板题,结果后三个点超时. 又把询问改成链式前向星,才ok. 这个博客,tarjan分析的很详细. 附代码-- #in ...

  3. HDU 4547 CD操作 (LCA最近公共祖先Tarjan模版)

    CD操作 倍增法  https://i.cnblogs.com/EditPosts.aspx?postid=8605845 Time Limit : 10000/5000ms (Java/Other) ...

  4. LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现

    首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...

  5. LCA最近公共祖先 Tarjan离线算法

    学习博客:  http://noalgo.info/476.html 讲的很清楚! 对于一颗树,dfs遍历时,先向下遍历,并且用并查集维护当前节点和父节点的集合.这样如果关于当前节点(A)的关联节点( ...

  6. LCA 最近公共祖先 (模板)

    #include <iostream> #include <stdio.h> #include <cstring> #include <vector> ...

  7. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  8. LCA(最近公共祖先)模板

    Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...

  9. LCA 近期公共祖先 小结

    LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...

随机推荐

  1. spring cloud Eureka 服务注册发现与调用

    记录一下用spring cloud Eureka搭建服务注册与发现框架的过程. 为了创建spring项目方便,使用了STS. 一.Eureka注册中心 1.新建项目-Spring Starter Pr ...

  2. 文章点赞功能(Ajax)

    一.文章点赞样式构建 1.将base.html的css样式改为外部引入 将base.html的内嵌样式删除,改为使用 HTML 头部的 <head> 标签对中使用<link>标 ...

  3. BZOJ2535: [Noi2010]Plane 航空管制2(拓扑排序 贪心)

    题意 题目链接 Sol 非常妙的一道题. 首先不难想到拓扑排序,但是直接对原图按\(k\)从小到大拓扑排序是错的.因为当前的\(k\)大并不意味着后面的点\(k\)也大 但是在反图上按\(k\)从大到 ...

  4. Topcoder SRM 563 Div1 500 SpellCards

    题意 [题目链接]这怎么发链接啊..... 有\(n\)张符卡排成一个队列,每张符卡有两个属性,等级\(li\)和伤害\(di\). 你可以做任意次操作,每次操作为以下二者之一: 把队首的符卡移动到队 ...

  5. 05_Jedis操作Redis

    [工程截图] [String类型操作] package com.higgin.string; import java.util.List; import redis.clients.jedis.Jed ...

  6. Windows7中Java64位环境变量配置:javac不是内部命令或外部命令,也不是可运行的程序或批处理文件。

    按照默认设置安装完JDK(Java Developement Kits)后,一般默认路径为:C:\Program Files\Java\jdk1.8.0_05_x64\文件夹. 然后配置环境变量:&q ...

  7. windows默认共享的打开和关闭?

    windows默认共享的打开和关闭?   Windows启动时都会默认打开admin$ ipc$ 和每个盘符的共享,对于不必要的默认共享,一般都会把它取消掉,可当又需要打开此默认共享时,又该从哪里设置 ...

  8. 1.GlusterFS 初识

    一. GlusterFS 初始 1.1 分布式文件系统出现 计算机通过文件系统管理.存储数据,而现在数据信息爆炸的时代中人们可以获取的数据成指数倍的增长,单纯通过增加硬盘个数来扩展计算机文件系统的存储 ...

  9. ORACLE不使用工具的情况下获取对象DDL

    set line 200set pagesize 0set long 99999set feedback offset echo off获得表.索引.视图.存储过程.函数的DDL:select dbm ...

  10. 【[JSOI2007]文本生成器】

    \(AC\)机上的计数\(dp\)啊 并没有想到反着求出不合法的串的个数,直接正面硬上 设\(dp[i][j][0/1]\)表示匹配出的长度为\(i\),在\(AC\)机上位置为\(j\),没有/有匹 ...