大体思路

1.求出每个元素在树中的深度

2.用st表预处理的方法处理出f[i][j],f[i][j]表示元素i上方第2^j行对应的祖先是谁

3.将较深的点向上挪,直到两结点的深度相同

4.深度相同后,祖先可能就在上方,再走几步就到了,于是两个点同时向上移

具体的方法和代码贴在下面 ↓

具体

1.求出每个元素在树中的深度

//求每个节点在树中的深度
void dfs(int pos,int pre)//pre是pos的父节点
{
for(int i=;i<v[pos].size;i++)//枚举pos的子节点
{
register int t=v[pos][i];
if(t==pre)continue;//防止死循环
f[t][]=pos;dep[t]=dep[pos]+;
dfs(t,pos);//再从子节点向后枚举
}
}

2.用st表预处理的方法处理出f[i][j]

//求f数组(st表预处理)
for(int i=;(<<i)<=n;i++)
for(int j=;j<=n;j++)
f[j][i]=f[f[j][i-]][i-];
//f[i][j]表示元素i上方第2^j行对应的祖先是谁

3.先比较a,b两点哪个较深,将较深的点赋值给a

//把a节点变为a,b中较深的一个节点
int query(int a,int b)
{
if(dep[a]<dep[b])swap(a,b);
}

将较深的点向上挪,直到两结点的深度相同

//使a和b在同一个深度上
for(int i=;i>=;i--)
if(dep[f[a][i]]>=dep[b])
a=f[a][i];
//倒着循环是因为向上走的步数只会越来越小

4.深度相同后,祖先可能就在上方,再走几步就到了,于是两个点同时向上移

//同一深度后,再向上找公共祖先
for(int i=;i>=;i--)
if(f[a][i]!=f[b][i])
{
a=f[a][i];
b=f[b][i];
}

全部代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
vector<int> v[];
vector<int> w[];
int f[][];//f[i][j]表示i点向上2^j层的祖先
int g[][];//g[i][j]表示i点到从i向上2^j层的祖先的距离
int dep[];
int n,m;
void dfs(int pos,int pre,int depth)
{
dep[pos]=depth;
for(int i=;i<v[pos].size();i++)
{
int t=v[pos][i];
if(t==pre) continue;
f[t][]=pos;
g[t][]=w[pos][i];
dfs(t,pos,depth+);
}
}
int query(int a,int b)
{
int sum=;
if(dep[a]<dep[b]) swap(a,b);//深度较深的点
for(int i=;i>=;i--)//找到a在深度dep[b]处的祖先
{
if(dep[f[a][i]]>=dep[b])
{
sum+=g[a][i];//a到该祖先的距离
a=f[a][i];
}
}
if(a==b) return sum;//挪到相同深度后如果在同一点直接return
int x;
for(int i=;i>=;i--)//否则a和b一起往上蹦跶
{
if(f[a][i]!=f[b][i])
{
sum+=g[a][i];
a=f[a][i];
sum+=g[b][i];
b=f[b][i];
}
}
return sum+g[a][]+g[b][];//最后蹦跶到最近公共祖先的下一层,所以要再加上上一层
}
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%d%d",&n,&m);
memset(dep,-,sizeof dep);//多组数据我们初始化
memset(f,,sizeof f);
memset(g,,sizeof g);
for(int i=;i<n;i++)//md
v[i].clear(),w[i].clear();
for(int i=;i<n;i++)
{
int x,y,c;
cin>>x>>y>>c;
v[x].push_back(y);
w[x].push_back(c);
v[y].push_back(x);
w[y].push_back(c);
}
int xxx=v[].size();
dfs(,,);//dfs处理出每个点的深度,以及各种... for(int i=;<<i<=n;i++)
for(int j=;j<=n;j++)
f[j][i]=f[f[j][i-]][i-],
g[j][i]=g[f[j][i-]][i-]+g[j][i-];
for(int i=;i<=m;i++)
{
int x,y;
cin>>x>>y;
if(x==y) cout<<""<<endl;
else cout<<query(x,y)<<endl;
}
}
return ;
}

lca最近公共祖先(st表/倍增)的更多相关文章

  1. lca最近公共祖先与树上倍增。

    https://vjudge.net/contest/295298#problem/A lca 的题目 求任意两点的距离. A题是在线算法,用st表rmq来实现. https://blog.csdn. ...

  2. LCA最近公共祖先 ST+RMQ在线算法

    对于一类题目,是一棵树或者森林,有多次查询,求2点间的距离,可以用LCA来解决.     这一类的问题有2中解决方法.第一种就是tarjan的离线算法,还有一中是基于ST算法的在线算法.复杂度都是O( ...

  3. LCA(最近公共祖先)之倍增算法

    概述 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 如图,3和5的最近公共祖先是1,5和2的最近公共祖先是4 在本篇中我们先介 ...

  4. 求LCA最近公共祖先的在线倍增算法模板_C++

    倍增求 LCA 是在线的,而且比 ST 好写多了,理解起来比 ST 和 Tarjan 都容易,于是就自行脑补吧,代码写得容易看懂 关键理解 f[i][j] 表示 i 号节点的第 2j 个父亲,也就是往 ...

  5. LCA(最近公共祖先)模板

    Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...

  6. CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )

    CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...

  7. LCA 近期公共祖先 小结

    LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...

  8. lca 最近公共祖先

    http://poj.org/problem?id=1330 #include<cstdio> #include<cstring> #include<algorithm& ...

  9. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  10. LCA近期公共祖先

    LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...

随机推荐

  1. SQL语法之初级增删改查

    SQL语法之初级增删改查 1.增 1.1插入单行 INSERT INTO [表名](列名) VALUES(列值) 语法如下: INSERT INTO bsp_Nproductclass(guid,pi ...

  2. java.util.ResourceBundle国际化用法详解

    java.util.ResourceBundle国际化用法详解 初识国际化和ResourceBundle 这个类主要用来解决国际化和本地化问题.国际化和本地化可不是两个概念,两者都是一起出现的.可以说 ...

  3. 解决使用mybatis做批量操作时发生的异常:Parameter '__frch_item_0' not found. Available parameters are [list] 记录

    本文主要描述 使用mybatis进行批量更新.批量插入 过程中遇到的异常及总结: 首先贴出使用批量操作报的异常信息: java.lang.RuntimeException: org.mybatis.s ...

  4. ceres求解BA第10章

    1.前言g2o是根据边来保存每一个代价函数,它是在边类中构造误差函数,构造边的时候,会设置顶点.测量值.协方差矩阵等.而在ceres中,用problem类型来构造最终的目标函数.先是使用AddResi ...

  5. python类初探

    class human: is_alive=True is_man=True def __init__(self,age): print('this is __init__() method, whi ...

  6. 金色酒类企业dedecms模板

    金色酒类企业dedecms模板,网站模板,dedecms模板. 模板地址:http://www.huiyi8.com/sc/7276.html

  7. 一步一步教你简单完成 Android USB开发

    项目中有一个新的需求,要求可以连接一个USB体温枪,APP可以从体温枪中读取到体温数据,一番搜寻之后发现一个封装很棒的USB通信库. github地址:usb-serial-for-android 准 ...

  8. 深度学习在gilt应用——用图像相似性搜索引擎来商品推荐和服务属性分类

    机器学习起源于神经网络,而深度学习是机器学习的一个快速发展的子领域.最近的一些算法的进步和GPU并行计算的使用,使得基于深度学习的算法可以在围棋和其他的一些实际应用里取得很好的成绩. 时尚产业是深度学 ...

  9. css:before和after中的content属性

    css有一个属性叫做content.content只能使用在:after和:before之中.它用于在元素之前或者元素之后加上一些内容 就像这样: .email-address:before { co ...

  10. 无言以队Alpha阶段项目复审

    小组的名字和链接 优点 缺点,bug报告 (至少140字) 最终名次 (无并列) 甜美女孩 http://www.cnblogs.com/serendipity-zeng/p/9937832.html ...