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. 利用ajax短轮询+php与服务器交互制作简易即时聊天网站

    主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Server-sent Events). 本文主要介绍ajax短轮询的简易实现方式. 看懂此文 ...

  2. scss-变量分隔符

    scss的变量名可以与css中的属性名和选择器名称相同,包括中划线和下划线. 在使用中划线还是下划线来进行变量分隔完全根据个人喜好. scss完全兼容这两种写法,也就是说scss认为中划线和下划线是完 ...

  3. IOS微信浏览器点击事件不起作用问题

    问题: $(document).on("click",".btn",function(){alert("1")}); 在微信浏览器上点击不起 ...

  4. Android 仿iPhone的日期时间选择器

    可选只选择日期,也可以同时选择时间 只选择日期的情况 同时选择日期和时间的情况 关键代码: findViewById(R.id.selectDateButton).setOnClickListener ...

  5. python 继承式多线程

    Thread是线程类,有两种使用方法,直接传入要运行的方法或从Thread继承并覆盖run(): Thread继承 import threading import time class MyThrea ...

  6. 互联网部-供应商团队js规范

    文件命名 页面.js文件命名:采用中划线连接方式,比如说: error-report.html js文件夹命名:scripts 公共js命名:common.js 文件结构组织 每个页面中中独有的js文 ...

  7. 64位系统中连接Access数据库文件的一个问题

    近日在windows 7 64位系统中编译以前写的程序,发现在连接Access数据库时总是出现异常,提示“Microsoft.Jet.OLEDB.4.0”未在本机注册,同样的代码在32位的xp系统中却 ...

  8. Dynamics CRM 批量新建域用户

    好久没写了,今天大牛教了我偷懒的批量新建域用户的方法 是不是觉得  控制面板 =>管理工具=>用户和计算机=>Users=>新建用户,一个个建,很烦是不是,而且耗时,我上个项目 ...

  9. HCNA多区域OSPF配置

    1.拓扑图 2.各路由器配置角本 ospf 多区域配置 #R5配置 sys sysname AR5 interface s2// ip add 10.0.35.5 255.255.255.0 inte ...

  10. Struts2学习-拦截器

    1.新建项目user4,建立好和user3一样的目录,与之相比只是添加几个类,主要是struts.xml和action类的改变,其结果没有太大的变化 struts,xml <?xml versi ...