题意:求最近公共祖先。

解题关键:三种方法,1、st表 2、倍增法 3、tarjan

此次使用倍增模板(最好采用第一种,第二种纯粹是习惯)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m,root,cnt,u,v,head[],dep[],fa[][];
struct edge{
int nxt;
int to;
}e[];
void add_edge(int u,int v){//单向
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
void dfs(int u){
for(int i=;(<<i)<=dep[u];i++){
fa[u][i]=fa[fa[u][i-]][i-];
}
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].to;
if(v==fa[u][]) continue;
fa[v][]=u;
dep[v]=dep[u]+;
dfs(v);
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
int d=dep[u]-dep[v];
for(int i=;(<<i)<=d;i++) if(d&(<<i)) u=fa[u][i];//转化到两节点深度相同,类似于快速幂的思想
if(u==v) return u;
for(int i=;i>=;i--){
if(fa[u][i]!=fa[v][i]){
u=fa[u][i];
v=fa[v][i];
}
}
return fa[u][];
}
int main(){
memset(head,-,sizeof head);
scanf("%d%d%d",&n,&m,&root);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(root);
while(m--){
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return ;
}

2、熟悉的树dp方式

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m,root,cnt,u,v,head[],dep[],par[][];
struct edge{
int nxt;
int to;
}e[];
void add_edge(int u,int v){//单向
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
void dfs(int u,int fa){
for(int i=;(<<i)<=dep[u];i++){
par[u][i]=par[par[u][i-]][i-];
}
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
par[v][]=u;
dep[v]=dep[u]+;
dfs(v,u);
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
int d=dep[u]-dep[v];
for(int i=;(<<i)<=d;i++) if(d&(<<i)) u=par[u][i];//转化到两节点深度相同,类似于快速幂的思想
if(u==v) return u;
for(int i=;i>=;i--){
if(par[u][i]!=par[v][i]){
u=par[u][i];
v=par[v][i];
}
}
return par[u][];
}
int main(){
memset(head,-,sizeof head);
scanf("%d%d%d",&n,&m,&root);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(root,-);
while(m--){
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return ;
}

[luogu3379]最近公共祖先(树上倍增求LCA)的更多相关文章

  1. 树上倍增求LCA(最近公共祖先)

    前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...

  2. [算法]树上倍增求LCA

    LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...

  3. [学习笔记] 树上倍增求LCA

    倍增这种东西,听起来挺高级,其实功能还没有线段树强大.线段树支持修改.查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨. ...

  4. 树上倍增求LCA及例题

    先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...

  5. 树上倍增求LCA详解

    LCA(least common ancestors)最近公共祖先 指的就是对于一棵有根树,若结点z既是x的祖先,也是y的祖先(不要告诉我你不知道什么是祖先),那么z就是结点x和y的最近公共祖先. 定 ...

  6. Codeforces 609E (Kruskal求最小生成树+树上倍增求LCA)

    题面 传送门 题目大意: 给定一个无向连通带权图G,对于每条边(u,v,w)" role="presentation" style="position: rel ...

  7. CF 519E(树上倍增求lca)

    传送门:A and B and Lecture Rooms 题意:给定一棵树,每次询问到达点u,v距离相等的点有多少个. 分析:按情况考虑: 1.abs(deep[u]-deep[v])%2==1时, ...

  8. 树上倍增求LCA

    大概思想就是,节点$i$的第$2^{j}$个父节点是他第$2^{j-1}$个父亲的第$2^{j-1}$个父亲 然后可以$O(nlogn)$时间内解决…… 没了? //fa[i][j]表示i的第2^j个 ...

  9. 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))

    倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...

随机推荐

  1. LINQ to Entities 不识别方法“Int32 ToInt32(System.String)”,因此该方法无法转换为存储表达式。

      通常原始代码如下: Where id=Convert.ToInt32(cousid) 更改后代码: Var currentid= Convert.ToInt32(cousid); Wehre id ...

  2. delphi 数据连接规范

    建议大家采用另外一种编码风格,不要在程序中到处都有这种LZ程序生成的代码: begin with qryMain do begin try Close; SQL.Clear; SQL.Add('Del ...

  3. 解决:SyntaxError: Non-ASCII character in file

    今天尝试用monkeyrunner脚本在夜神模拟器上安装并截图QQ,但是遇到了一些问题: from com.android.monkeyrunner import MonkeyRunner, Monk ...

  4. svg札记

    1.人老了,有些事情太容易忘记了,这里做下笔记,供参考,for self for you. 2.源于地图监控,建筑级别各大地图商的api(高德.百度.腾讯等)已经足够使用,唯独室内图这块还差点. 3. ...

  5. 简单的说一下:tarits技法就是一种模板元编程,起可以将本来处于运行期的事拉到编译期来做,增加了运行效率。 看以非模板元编程的例子,就是前面的那个例子:

    void adance(std::list<int>::iterator& iter, int d) { if(typeid(std::iterator_traits<std ...

  6. L118

    The company needs to focus on its biggest clients.This article discussed the events that led to her ...

  7. js字符串和数组操作,容易混淆的方法总结(slice、substring、substr、splice)

    平时工作中,很少静下心来总结基础知识,总觉得自己会用了,有点飘了,直到碰壁之后才懂得基础知识的重要性.大牛告诉我,一次写对,是不是可以不用F12去调试了?是不是省了时间?简直是面红耳赤,无地自容.在这 ...

  8. Codeforces Round #258 (Div. 2)C(暴力枚举)

    就枚举四种情况,哪种能行就是yes了.很简单,关键是写法,我写的又丑又长...看了zhanyl的写法顿时心生敬佩.写的干净利落,简直美如画...这是功力的体现! 以下是zhanyl的写法,转载在此以供 ...

  9. [基本操作] Mobius 反演, Dirichlet 卷积和杜教筛

    Dirichlet 卷积是两个定义域在正整数上的函数的如下运算,符号为 $*$ $(f * g)(n) = \sum_{d|n}f(d)g(\frac{n}{d})$ 如果不强调 $n$ 可简写为 $ ...

  10. LeetCode Reverse Words in a String III

    原题链接在这里:https://leetcode.com/problems/reverse-words-in-a-string-iii/#/description 题目: Given a string ...