看了好多dalao的博客,就总结一下啦ovo

tarjian算法很是神奇,它的作用是求lca。它是一种离线算法。

在线是指输入一个询问输出一个结果。

离线是将询问一次性输入,一起处理。

tarjan它是将m个询问打乱顺序,在每个结点上挂上它的询问,利用dfs和并查集进行处理。

对于一个结点u,如果要找(u,v)的lca,u和v的关系分为以下几种情况:

(1)结点v在u的子树中,那么lca(u,v)=u;

(2)  结点v不在u的子树中,那么v就在u子结点以外的结点中。v可能在u的爸爸的子树中,那么lca(u,v)=u的爸爸;

(3)如果v不在u的爸爸的子树中,那么v可能在u的爸爸的爸爸的子树中,lca(u,v)=u的爸爸的爸爸;

发现找爸爸的过程好像和并查集的操作很像哦.

【代码】

#include<bits/stdc++.h>
using namespace std;
#define N 10000
vector<int>vec[N];
vector<int>que[N];
int dad[N],far[N],qx[N],qy[N];
int n,m,x,y,ans[N];
int f(int x)
{
return far[x]==x?x:far[x]=f(far[x]);
}
void dfs(int x)
{
far[x]=x;
for(int i=;i<vec[x].size();i++)
{
if(dad[x]!=vec[x][i])
{
dad[vec[x][i]]=x;
dfs(vec[x][i]);
}
}
for(int i=;i<que[x].size();i++)
{
if(dad[y=qx[que[x][i]]^qy[que[x][i]]]^x)//y是x结点的一个询问;x^x^y=y;
{
ans[que[x][i]]=f(y);
}
}
far[x]=dad[x];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d%d",&x,&y);
vec[x].push_back(y);
vec[y].push_back(x);
}
for(int i=;i<=m;i++)
{
scanf("%d%d",&qx[i],&qy[i]);
que[qx[i]].push_back(i);//在每个结点上挂上它的询问是第几个询问;
que[qy[i]].push_back(i);
}
dfs();
for(int i=;i<=m;i++)
{
printf("%d ",ans[i]);//每个询问的答案’
}
return ;
}

tarjian求lca的更多相关文章

  1. 【模板】Tarjian求LCA

    概念 公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点 举个例子吧,如下图所示4和5的最近公共祖先是2,5和3的最近公共祖先是1,2和1的最近公共祖先是1. 算法 常用的求LCA的算法有:Ta ...

  2. 树链剖分求LCA

    树链剖分中各种数组的作用: siz[]数组,用来保存以x为根的子树节点个数 top[]数组,用来保存当前节点的所在链的顶端节点 son[]数组,用来保存重儿子 dep[]数组,用来保存当前节点的深度 ...

  3. 树上倍增求LCA(最近公共祖先)

    前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...

  4. [算法]树上倍增求LCA

    LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...

  5. 【树链剖分】洛谷P3379 树链剖分求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  6. 【倍增】洛谷P3379 倍增求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  7. 【RMQ】洛谷P3379 RMQ求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  8. 【Tarjan】洛谷P3379 Tarjan求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  9. 树上倍增求LCA及例题

    先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...

随机推荐

  1. docker安装并配置加速

    安装 旧版本的 Docker 称为 docker 或者 docker-engine,使用以下命令卸载旧版本: sudo apt-get remove docker \ docker-engine \ ...

  2. SuperAgent使用文档

    SuperAgent是一个轻量级.灵活的.易读的.低学习曲线的客户端请求代理模块,使用在NodeJS环境中.官方文档:http://visionmedia.github.io/superagent 简 ...

  3. Unable to determine IP address from host name

  4. spring属性注入方式

    一.使用有参构造注入属性 配置文件 constructor-arg标签是需注入属性的名字 User类 生成了User的有参构造函数 测试类 结果 打印出了name属性的值 二.使用set方法注入属性 ...

  5. C#基础知识之三

    C#基础知识之三 1.  程序集间的继承:基类必须被声明为public.必须在project中包含对该基类的程序集引用. 2.  对其它程序集引用和添加对using指令的差别:前者是告诉编译器所需的类 ...

  6. 解决oracle锁表

    1.查看被锁住的表select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects ...

  7. Android 常用的权限

    添加WiFi以及访问网络的权限:    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE&q ...

  8. 关于align-items和align-content的区别和使用场景

    最近在研究flex布局,容器中有两个属性,是用来定义crossAxis测轴排列方式的.一开始接触align-items还可以理解感觉不难,后来看到align-content就感觉有点混淆了,特开一篇博 ...

  9. linux 基础2-null,cut,wc,head,tail

    一. 特殊文件: /dev/null和/dev/tty Linux系统提供了两个对Shell编程非常有用的特殊文件,/dev/null和/dev/tty.其中/dev/null将会丢掉所有写入它的数据 ...

  10. linux下查找最耗iowait的进程

    抓哪个进程干坏事前要先停掉syslogservice syslog stop 打开block dump:echo 1 > /proc/sys/vm/block_dump 统计:dmesg | e ...