P3379 【模板】最近公共祖先(LCA) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

1.Tarjan

观察这样一棵树,假设要求LCA(3,4),根据dfs我们会先向下搜索

我们先会来到2,然后到3,3无子节点,搜索结束,开始回溯,回溯的第一个节点就是他本身3,此时有询问LCA(3,4)于是我们查看4,发现4还没有遍历到,跳过这个询问.之后程序从3回溯到2,没有关于2的询问而且2也没有其他分支可以走,2继续回溯到1也没有1的询问但是1有一个分支没有走,dfs从1搜索到4,4无子节点,搜索结束,开始回溯,4首先从4开始回溯,有关于4的询问LCA(3,4),判断3是否回溯过,答案是已经回溯了3。所以此时取已经完全回溯完的那个节点的根节点,也就是3。由并查集find实现,发现3的根节点是1,所以LCA(3,4)就是1.

这是一个很简单的例子,但是足够模拟Tarjan求LCA的过程了。就是根据后序遍历,并查集保存根节点,在向后回溯的时候第一个满足要求的就是LCA

#include <bits/stdc++.h>
#include<iostream>
#include<thread>
using namespace std;
#pragma warning(disable:4996);
#define ll signed long long
#define int ll
#define rep(j,b,e) for(register int j=b;j<=e;j++)
#define drep(j,e,b) for(register int j=(e);j>=(b);j--)
int T = 1;
const int N = 5e5 + 10;
const int mod = 10000;
int n, m, k, q;template <class T, class ...Arg>
void inline pln(T t, Arg ...args);//打印一行参数
template<typename T>
void inline pln(vector<T> a, string s = " ");
template<class T, class ...Arg>
void inline  inln(T& t, Arg&...args);//输入一行数据
//--------------------------------------
vector<int>gra[N];
vector<pair<int, int>>query[N];
vector<int>vis(N);
vector<int>pre(N);
vector<int>ans(N);
void init(int n) {rep(j, 1, n)pre[j] = j;
}
int fnd(int k) {return pre[k] == k ? k : pre[k] = fnd(pre[k]);
}
int used[N];
void tarjan(int now,int f) {vis[now] = 1;for (auto nx : gra[now]) {if (vis[nx] == 0&&f!=nx) {tarjan(nx,now);pre[nx] = now;//回溯的时候更新父节点}}for (auto [b, id] : query[now]) {if (vis[b] == 1&&used[id]==0) {//如果被访问过,说明在一个根节点下ans[id] = fnd(b);//最近公共祖先为之前已经更新完其路径上全部父节点的根节点used[id] = 1;//重复的询问可以跳过}}}
signed main()
{
#ifndef ONLINE_JUDGE//freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifint r;inln(n, q, r);init(n);rep(j, 1, n - 1) {int f, t;inln(f, t);gra[f].push_back(t);gra[t].push_back(f);}rep(j, 1, q) {int a, b;inln(a, b);if (a == b)ans[j] = a;else {query[a].push_back({ b,j });query[b].push_back({ a,j });}}tarjan(r,0);rep(j, 1, q) {pln(ans[j]);}return 0;
}//--------------------------------------
void inline  inln() {}
template<class T, class ...Arg>
void inline  inln(T& t, Arg&...args) {cin >> t;inln(args...);
}
void inline pln() {cout << "\n";
}
template <class T, class ...Arg>
void inline pln(T t, Arg ...args) {cout << t << " ";pln(args...);
}
template<typename T>
void inline pln(vector<T> a, string s) {for (T& x : a) {cout << x << s;}cout << endl;
}

最近公共祖先(LCA)Tarjan相关推荐

  1. 最近公共祖先 LCA Tarjan算法

    来自:http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html 对于一棵有根树,就会有父亲结点,祖先结点,当然最近公共祖先就是这两个 ...

  2. 【C++】最近公共祖先 LCA

    最近公共祖先 百科名片 简单引入 LCA的算法 暴力枚举法 Tarjan离线算法 倍增算法 例题: 题目描述 输入描述 输出描述 样例输入 样例输出 代码 百科名片 最近公共祖先 Lowest Com ...

  3. 图论--最近公共祖先LCA

    最近公共祖先LCA LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先) 最近公 ...

  4. POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)...

    POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...

  5. 最近公共祖先 (LCA) [No. 21]

    问题: 给定一个二叉树,找到两个节点NA, NB的最近公共祖先(LCA). 比如对于下图,4 和 7 的 LCA 是6, 1和13的LCA 是 8. 我们这里先考虑一般的二叉树(BT),然后再考虑这个 ...

  6. 树上倍增法求最近公共祖先LCA

    LCA,最近公共祖先,这个东西有很多作用,因此,如何高效求出LCA就成了一个热点的讨论话题. 下面所有的讨论都以图中这棵树为例子. 先来了解下什么是倍增吧,倍增其实就是二分的逆向,二分是逐渐缩小范围, ...

  7. POJ 1470 Closest Common Ancestors (最近公共祖先LCA 的离线算法Tarjan)

    Tarjan算法的详细介绍,请戳: http://www.cnblogs.com/chenxiwenruo/p/3529533.html #include <iostream> #incl ...

  8. POJ 1330 LCA最近公共祖先 离线tarjan算法

    题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集 ...

  9. 与图论的邂逅05:最近公共祖先LCA

    什么是LCA? 祖先链 对于一棵树T,若它的根节点是r,对于任意一个树上的节点x,从r走到x的路径是唯一的(显然),那么这条路径上的点都是并且只有这些点是x的祖先.这些点组成的链(或者说路径)就是x的 ...

  10. 最近公共祖先LCA 【专题@AbandonZHANG】

    参考: <算法艺术与信息学竞赛> --- 刘汝佳 博客:http://blog.163.com/kevinlee_2010/blog/static/16982082020120794613 ...

最新文章

  1. angular之Rxjs异步数据流编程入门
  2. 禁用DropDownList某一选项
  3. php5.6 连接 oracle,XAMPP中PHP5.6.3连接Oracle
  4. 小牛地图矢量抓取工具_SEO优化网站sitemap需要注意哪些要点才能很好的被百度蜘蛛抓取...
  5. 设置java环境变量生效 centos_解决CentOS java环境不生效的问题
  6. 常用音频软件:Cool edit pro
  7. 有36匹马,六个跑道。没有记时器等设备,用最少的比赛次数算出跑的最快的前3匹马
  8. 发布一个基于 Reactor 模式的 C++ 网络库
  9. mysql 文章 字段设计_在mysql数据库中,文章表设计有啥好的思路
  10. python正则匹配11个数字_Python正则表达式匹配字符串中的数字
  11. 移远EC20 4G模块Linux驱动移植和测试
  12. 支持select下拉框选择输入和键盘输入两种输入方式并且支持手动换行
  13. 基于Java的Office 系列文档处理五种工具简单介绍
  14. VMware安装win10:需win10虚拟机专用镜像,不是真机装系统的ISO镜像
  15. 用三元组存储稀疏矩阵,实现其快速转置及矩阵相乘
  16. Minimum Class Confusion for Versatile Domain Adaptation
  17. 建造者模式实现汽车组装工厂功能(Java代码实例)
  18. 彻底搞懂MySQL的索引
  19. ping ping ping
  20. 计算机网络知识点整理(笔试面试)

热门文章

  1. 阶乘约数【蓝桥杯国赛】
  2. 【JAVA】水仙花数
  3. 会计学原理学习笔记——第三章——账户与复式记账(3.5生产准备业务核算——费用发生业务核算)
  4. springboot2稳定版本_springboot 最新稳定版
  5. Phonics 自然拼读法 s,a,t,i,p,n Teacher:Lamb
  6. 软件发布版本区别介绍
  7. 12 Roll A Ball全部代码
  8. gitlab 分支保护
  9. 如何搭建数据指标监测体系?
  10. 【8082端口被占用】