看了好多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. u-boot下载模式LCD显示图片修改方法(基于TQ2440)

    1.明确液晶型号,这点非常重要,我手头的液晶是天嵌4.3寸屏,让人很郁闷的是液晶背面竟然写着LCD 3.5,这一点让我在上面浪费了好几个小时: 2.根据液晶型号,修改u-boot1.1.6--> ...

  2. tomcat6指定的服务为安装

    tomcat6w.exe 运行 提示 指定的服务未安装 unable to open the service 'tomcat6' 新下载的Tomcat6.0.29 解压版,解压缩完成后,双击tomca ...

  3. C# 6.0 (C# vNext) 新功能之:Null-Conditional Operator(转)

    Null-Conditional Operator 也叫 Null propagating operator 也叫 Safe Navigation Operator 看名字,应该就有点概念了.如果还不 ...

  4. python查询IP地址所属地

    1.linux命令行版 #!/usr/bin/python #-*- coding: utf-8 -*- import json import urllib import sys def get_da ...

  5. csv .xlsx

    def gen_file_data(fodir, fname, sheet_index=0, ): if fname.find('.xlsx') > -1: fname_open = '%s\\ ...

  6. spring属性注入方式

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

  7. ob 函数讲解

    ob的基本原则:如果ob缓存打开,则echo的数据首先放在ob缓存.如果是header信息,直接放在程序缓存.当页面履行到最后,会把ob缓存的数据放到程序缓存,然后依次返回给涉猎器.下面我说说ob的基 ...

  8. Android UI Design

    Ref:直接拿来用!10款实用Android UI工具 Ref:Android UI设计资源 Ref:Android酷炫实用的开源框架(UI框架) Ref:Android UI 组件 Ref:Andr ...

  9. IDEA main方法自动补全(转发:http://blog.csdn.net/zjx86320/article/details/52684601)

    最近刚从Eclipse转到IDEA,各种学习丫,IDEA里的main方法是不能自动补齐的,肿么办呢? 1.首先,点击File-->Settings-->Editor-->Live T ...

  10. Iptalbes练习题(三)

    场景需求: (1)员工在公司内部(192.168.124.0/24 ,192.168.122.0/24 )能访问服务器上任何服务 (2)当员工出差,通过VPN连接到公司 (3)公司门户网站允许公网访问 ...