看了好多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. yii2.0 console执行php守护进程

    //该方法只需执行一次public function actionIndex(){ $pid =pcntl_fork();//在当前进程中生成一个新的子进程 //$pid会有三种形式 $pid==-1 ...

  2. centos7.0 增加/usr分区的容量减少home分区的大小

    把/home内容备份,然后将/home文件系统所在的逻辑卷删除,扩大/root文件系统,新建/home:tar cvf /tmp/home.tar /home #备份/homeumount /home ...

  3. 【BZOJ3784】树上的路径 点分治序+ST表

    [BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...

  4. 牛人blog汇总

    1.天一思维: https://blog.csdn.net/tszty1997?t=1

  5. javascript中apply和call的区别

    请补充   136页  pdf  高级javascript设计

  6. linux c编程:线程互斥一

    当多个线程共享相同的内存的时候,需要确保每个线程都看到一致的数据视图.如果每个线程使用的变量都是其他线程不会读取和修改的.那么就不存在一致性问题.同样,如果变量是只读的,多个线程也不会有一致性的问题. ...

  7. strstr使用

    extern char strstr(char str1, const char *str2); 语法: strstr(str1,str2) str1: 被查找目标 string expression ...

  8. mysql 修改表名的方法:sql语句

    在使用mysql时,经常遇到表名不符合规范或标准,但是表里已经有大量的数据了,如何保留数据,只更改表名呢? 可以通过建一个相同的表结构的表,把原来的数据导入到新表中,但是这样视乎很麻烦. 能否简单使用 ...

  9. pinpoint改造支持查询

    原架构 改造后架构

  10. 装箱问题【STL】

    7-9 装箱问题(20 分) 假设有N项物品,大小分别为s​1​​.s​2​​.-.s​i​​.-.s​N​​,其中s​i​​为满足1≤s​i​​≤100的整数.要把这些物品装入到容量为100的一批箱 ...