树链剖分求LCA
树链剖分中各种数组的作用:
siz[]数组,用来保存以x为根的子树节点个数
top[]数组,用来保存当前节点的所在链的顶端节点
son[]数组,用来保存重儿子
dep[]数组,用来保存当前节点的深度
fa[]数组,用来保存当前节点的父亲
tid[]数组,用来保存树中每个节点剖分后的新编号
rank[]数组,用来保存当前节点在线段树中的位置
树链剖分求LCA据说很快QWQ,反正我在洛谷上评测的时候比倍增整整快了3分之1.
蓝后我们来说怎么用树链剖分求:

1,第一种情况我们要比较的数在一条链上,比如比较3和12,直接返回深度比较小的数就好了
2,第二种情况我们要比较不在一条链上的两个数,比如我们想求一下10和8的LCA,我们只需要比较一下10和8的重链链顶的深度,我们发现竟然一样深,那我们就用比较早发现的10的链顶就好了,我们吧我们要比较的元素变为自己链顶的父亲(这样就可以实现垮链了),所以近下来我们只需要比较3和8就好,我们发现3和8不在一条链上,所以我们比较3和8链顶的深度,发现8的比较深,所以我们把我们要比较的数变成8的链顶的父亲,也就是3,所以这时候我们要比较的数就都在一条链上了,返回深度比较浅的数就好。
今下来是代码环节,我写了洛谷的3379模板题https://www.luogu.org/problem/show?pid=3379#sub
然后我把我ac的代码粘到这里QWQ
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 1000 struct NODE{
int point,next;
NODE(){next=;};
}edge[MAX<<]; int N,M,S;
int siz[MAX],dep[MAX],son[MAX],fa[MAX];
int top[MAX],tip[MAX],rank[MAX],tim=;
int edgenum=,link[MAX]; void ADD(int a,int b)
{
edgenum++;
edge[edgenum].point=b;
edge[edgenum].next=link[a];
link[a]=edgenum;
} void pt()
{
for(int i=;i<=N;i++){
printf("%3d",i);
}
cout<<endl;
for(int i=;i<=N;i++){
printf("%3d",top[i]);
}
} void DFS(int x,int deep)
{
siz[x]=;
dep[x]=deep;
for(int i=link[x];i;i=edge[i].next){
int v=edge[i].point;
if(v!=fa[x]){
fa[v]=x;
DFS(v,deep+);
siz[x]+=siz[v];
if(son[x]==-||siz[v]>siz[son[x]]){
son[x]=v;
}
}
}
} void DFS2(int x,int tp)
{
//cout<<"!";
top[x]=tp;
tip[x]=++tim;
rank[tip[x]]=x;
if(son[x]==-)return ;
DFS2(son[x],tp);
for(int i=link[x];i;i=edge[i].next){
int v=edge[i].point;
if(v!=son[x]&&v!=fa[x]){
DFS2(v,v);
}
}
} int LCA(int a,int b) //重点的注释都在这里
{
while(top[a]!=top[b]){ //如果两个的链顶不相等,我们就把他们往一起靠
if(dep[top[a]]>dep[top[b]]) //看那个点的链顶深度大改变那个点
a=fa[top[a]];
else
b=fa[top[b]];
}
return dep[a]>dep[b]?b:a; //返回时要返回深度比较小的数
} void init()
{
int a,b;
cin>>N>>M>>S;
for(int i=;i<N;i++){
scanf("%d%d%*c",&a,&b);
ADD(a,b);
ADD(b,a);
}
memset(son,-,sizeof(siz));
} void work()
{
int a,b;
for(int i=;i<=M;i++){
scanf("%d%d%*c",&a,&b);
printf("%d\n",LCA(a,b));
}
} int main()
{
init();//初始化
DFS(S,);//树链剖分。两个dfs就行
DFS2(S,S);
work(); //输入询问
//pt(); 调试函数,复制下来你们也可以用
//system("pause");
return ;
}
树链剖分求LCA的更多相关文章
- cogs 2450. 距离 树链剖分求LCA最近公共祖先 快速求树上两点距离 详细讲解 带注释!
2450. 距离 ★★ 输入文件:distance.in 输出文件:distance.out 简单对比时间限制:1 s 内存限制:256 MB [题目描述] 在一个村子里有N个房子,一 ...
- cogs 2109. [NOIP 2015] 运输计划 提高组Day2T3 树链剖分求LCA 二分答案 差分
2109. [NOIP 2015] 运输计划 ★★★☆ 输入文件:transport.in 输出文件:transport.out 简单对比时间限制:3 s 内存限制:256 MB [题 ...
- HDU2586 How far away ? (树链剖分求LCA)
用树链剖分求LCA的模板: 1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const ...
- 【树链剖分】洛谷P3379 树链剖分求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 【POJ1330】Nearest Common Ancestors(树链剖分求LCA)
Description A rooted tree is a well-known data structure in computer science and engineering. An exa ...
- 【模板】树链剖分求LCA
洛谷3379 #include<cstdio> #include<algorithm> using namespace std; ,inf=1e9; int n,m,x,y,r ...
- Hdu 2586 树链剖分求LCA
Code: #include<cstdio> #include<cstring> #include<vector> #include<algorithm> ...
- Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)
Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...
- Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)
Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...
随机推荐
- 将图片的二进制字节 在HTML页面中显示
两种方法: 后端的一般处理程序:Imge.ashx using System; using System.Collections.Generic; using System.Linq; using S ...
- C++学习之重载、覆盖与隐藏
MaiziTest12.cpp : 定义控制台应用程序的入口点. 1.重载特征 1)相同的范围(在同一个类中): 2)函数名相同: 3)参数不同: 4)virtual关键字可有可无. 2.覆盖 指的是 ...
- 有jQuery背景,该如何用AngularJS编程思想?
"我可以熟练使用jQuery进行客户端应用的开发,但是现在我希望开始使用Angular.js.哪位能描述一下这个过程中必要的模式变化吗?希望您的答案能够围绕下面这些具体的问题: 1. 我如何 ...
- 【原创】.NET读写Excel工具Spire.Xls使用(2)Excel文件的控制
本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html .NET读写Excel工具Spire.Xls使用文章 ...
- 提高性能:用RequireJS优化Wijmo Web页面
上周Wijmo 2014 V2版本刚刚发布(下载地址), 有网友下载后发现仅仅使用了40个Widgets的一小部分,还需要加载全部的jquery.wijmo-pro.all.3.20142.45.m ...
- Android中的内存储、外存储概念、文件操作与PC端的有些不同
其实安卓文件的操作和java在pc环境下的操作并无二致,之所以需要单独讲解是因为安卓系统提供了不同于pc的访问文件系统根路径的api,同时对一个应用的私有文件做了统一的管理.初学者在这部分感到很容易混 ...
- 漫谈可视化Prefuse(五)---一款属于我自己的可视化工具
伴随着前期的基础积累,翻过API,读过一些Demo,总觉得自己已经摸透了Prefuse,小打小闹似乎已经无法满足内心膨胀的自己.还记得儿时看的<武状元苏乞儿>中降龙十八掌最后一张居然是空白 ...
- Azure ARM (7) ARM Template - 使用Visual Studio编辑
<Windows Azure Platform 系列文章目录> 之前介绍的ARM Template,都是使用文本编辑器来编辑JSON文件的. 文本讲介绍如何使用Visual Studio, ...
- 在java中使用redis
在java中使用redis很简单,只需要添加jedist.jar,通过它的api就可以了.而且,api和redis的语法几乎完全相同.以下简单的测试: 参考:http://www.runoob.com ...
- Java魔法堂:解读基于Type Erasure的泛型
一.前言 还记得JDK1.4时遍历列表的辛酸吗?我可是记忆犹新啊,那时因项目需求我从C#转身到Java的怀抱,然后因JDK1.4少了泛型这样语法糖(还有自动装箱.拆箱),让我受尽苦头啊,不过也反映自己 ...