首页 > 编程语言 >最近公共祖先 Tarjan算法

最近公共祖先 Tarjan算法

时间:2023-05-01 22:44:35浏览次数:45  
标签:Tarjan 祖先 back int 算法 read push query forup

例题:洛谷P3379 【模板】最近公共祖先(LCA)
https://www.luogu.com.cn/problem/P3379

tarjan算法是利用了并查集来求LCA的,时间复杂度比倍增低,是O(n+m)

#include<iostream>
#include<vector>
#include<utility>
#define forup(i,l,r) for(int i=l;i<=r;i++)
#define fordown(i,l,r) for(int i=r;i>=l;i--)
using namespace std;
const int N =5e5+5;
vector<int> child[N];//结点所连结点,此处为无向边 
vector<pair<int,int>> query[N];//询问组 
int fa[N];
bool vis[N];
int ans[N];//第n组询问的答案 
int read()
{
	int n=0;
	char m=getchar();
	while(m<'0'||m>'9') m=getchar();
	while(m>='0'&&m<='9'){
		n=(n<<1)+(n<<3)+(m^'0');
		m=getchar();
	}
	return n;
}
int find(int a)
{
	return fa[a]==a?a:fa[a]=find(fa[a]);
}
void tarjan(int u)
{
	vis[u]=true;//先标记 
	for(int c:child[u])//访问子节点,这里应该算是一个前序遍历,不过用了回溯,对每个结点的处理是后序遍历的
	{
		if(!vis[c]){
			tarjan(c);
			fa[c]=u;//回溯 
		}
	}
	for(pair<int,int> q:query[u])
	{
		int v=q.first,i=q.second;
		if(vis[v]) ans[i]=find(v);//由于回溯,相当于是从最左下的子树开始连fa,于是如果已经被遍历的话,那么这个子树的根就应该是u和v的最近公共祖先 
	}
}
int main()
{
	int n,m,root;
	n=read(),m=read(),root=read();
	forup(i,1,n-1)//存边 
	{
		int u,v;
		u=read(),v=read();
		child[u].push_back(v);
		child[v].push_back(u);
	}
	forup(i,1,m)//存询问 
	{
		int u,v;
		u=read(),v=read();
		query[u].push_back({v,i});
		query[v].push_back({u,i});//因为必然会有另外一个还没有vis的情况,于是要存双向的
	}
	forup(i,1,n) fa[i]=i;
	tarjan(root);
	forup(i,1,m) cout<<ans[i]<<endl;
	return 0;
 } 

参考:https://www.cnblogs.com/dx123/p/16320465.html

标签:Tarjan,祖先,back,int,算法,read,push,query,forup
From: https://www.cnblogs.com/V-sama/p/17367135.html

相关文章

  • 算法3:质数的个数
    一、质数的定义质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。二、判断质数的方法1for(intj=2;j<i;j++){2if(i%j==0)3break;4if(i==j)5cout<<i<<"";6}三、完整代码1#include<bits/stdc......
  • 推荐算法的知识框架【更新中】
    几年前刚进入行业时,就简单认为不过是wide&deep做精排,双塔FM做召回做粗排,再加上一些周边项目,比如冷启动和多模型融合调参,就组成了一个完整的推荐系统算法部分。再回头思考这一切,不再迷失在各式各样的实现细节中,关注本质,有了更广泛的认识,分为一下几个部分。1.建模方法多阶段的推......
  • 整理一些学过的数据结构和算法
    匆匆忙忙中学了很多算法,但基本都是打个板子就跑路了,有些算法有个人比较深入和独特的见解,但大部分,只是实现例题的需求,对算法的作用似懂非懂,所以写篇博客整理一下。无旋平衡树(treap)高级数据结构:树和堆可以允许的操作:插入,删除,查询某数排名,查询某排名的树(第K大),求某数的前驱,后驱(X......
  • 数据有偏差,照样能学对!20年前就有这么强的算法了?
    文|白鹡鸰给小铁比了个心编|小轶背景“每个人都依赖自己的知识和认知,同时又为之束缚,还将此称为现实;但知识和认识是非常暧昧的东西,现实也许不过是镜花水月——人们都是活在偏见之中的,你不这样认为吗?这双眼睛,又能看多远呢?”机器学习,作为模仿人类思维方法进行建模的过程,虽然从数......
  • 【字节二面算法】NO662 二叉树最大宽度
    [字节二面算法]662.二叉树最大宽度给你一棵二叉树的根节点root,返回树的最大宽度。树的最大宽度是所有层中最大的宽度。每一层的宽度被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的n......
  • 「学习笔记」SPFA 算法的优化
    与其说是SPFA算法的优化,倒不如说是Bellman-Ford算法的优化。栈优化将原本的bfs改为dfs,在寻找负环时可能有着更高效的效率,但是最坏复杂度为指数级别。voiddfs_spfa(intu){ if(fg)return; vis[u]=true; for(pilit:son[u]){ intv=it.first; llw=......
  • 线索化二叉树的递归算法
    //线索化二叉树的递归算法#include<stdio.h>#include<malloc.h>typedefstructBiTNode{intdata;structBiTNode*lchild,*rchild;//存储二叉树的左孩子和右孩子}BiTNode,*BiTree;typedefstructThreadNode{intdata;structThreadNode*......
  • m分别使用meanshift和camshift两种算法实现人员跟踪并输出人员移动曲线matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:    2.算法涉及理论知识概要       meanshift算法其实通过名字就可以看到该算法的核心,mean(均值),shift(偏移),简单的说,也就是有一个点,它的周围有很多个点 我们计算点 移动到每个点 所需要的偏移量之和,求平均,就得到......
  • 文心一言 VS chatgpt (13)-- 算法导论3.1 8题 3.2 1题
    八、可以扩展我们的记号到有两个参数n和m的情形,其中的n和m可以按不同速率独立地趋于无穷。对于给定的函数g(n,m),用O(g(n,m))来表示以下函数集:O(g(n,m))={f(n,m):存在正常量c、和,使得对所有n>=n0或m>=m0,有0<=f(n,m)<=cg(n,m)}对Ω(g(n,m))和θ(g(n,m))给出相应的定义。文......
  • 最近公共祖先
    倍增求LCA①初始化:通过bfs初始化两个数组depth[],fa[]\(\quad\)\(\quad\)depth[n]:表示深度(到根节点的距离加1)\(\quad\)\(\quad\)fa[i][j]:表示从i开始,向上走\(2^j\)步所能到的节点编号(\(0\leqslantj\leqslantlog_2n\))\(\quad\)\(\quad\)\(......