什么是欧拉序,可以去这个大佬的博客(https://www.cnblogs.com/stxy-ferryman/p/7741970.html)巨详细

因为欧拉序中的两点之间,就是两点遍历的过程,所以只要找遍历过程中对应的最小的深度就行了,这里用st表存,first存第一个u出现的地方,用value存欧拉序,同时用depth存对应深度

模板

 struct node{
int v,next,dist;
}a[maxn<<];
int n,m,tot,len;
int st[maxn<<][], depth[maxn<<],value[maxn<<],first[maxn<<];
int dist[maxn],head[maxn];
void add(int u,int v,int dist0){
a[tot].next=head[u];
a[tot].dist=dist0;
a[tot].v=v;
head[u]=tot++;
}
void dfs(int u,int fa,int d) {
value[++len]=u;depth[len]=d;first[u]=len;
for (int i=head[u];~i;i=a[i].next){
int v=a[i].v;if(v==fa)continue;
dist[v]=dist[u]+a[i].dist;
dfs(v,u,d+);
value[++len]=u;depth[len]=d;
}
}
inline void init(int n){
for(int i=;i<=n;i++)head[i]=-,depth[i]=;
tot=,len=;
}
inline void makest(){
for(it i=;i<=len;i++)st[i][]=depth[i];
for(it i=;<<i<=len;i++){
for(it j=;j+(<<i)-<=len;j++){
st[j][i]=min(st[j][i-],st[j+(<<(i-))][i-]);
}
}
}
inline int dis(int u,int v){
int l=first[u],r=first[v];
if(l>r){swap(l,r);}
int k=log2(r-l+);
int dep=min(st[l][k],st[r-(<<k)+][k]);
return dist[u]+dist[v]-*dist[value[first[dep]]];
}

题意:

以1为根的树,两个点之间的最近距离是多少

思路:

模板LCA

用欧拉序+st表

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define modd 998244353
const int maxn=4e4+;
struct node{
int v,next,dist;
}a[maxn<<];
int n,m,tot,len;
int st[maxn<<][], depth[maxn<<],value[maxn<<],first[maxn<<];
int dist[maxn],head[maxn];
void add(int u,int v,int dist0){
a[tot].next=head[u];
a[tot].dist=dist0;
a[tot].v=v;
head[u]=tot++;
}
void dfs(int u,int fa,int d) {
value[++len]=u;depth[len]=d;first[u]=len;
for (int i=head[u];~i;i=a[i].next){
int v=a[i].v;if(v==fa)continue;
dist[v]=dist[u]+a[i].dist;
dfs(v,u,d+);
value[++len]=u;depth[len]=d;
}
}
inline void init(int n){
for(int i=;i<=n;i++)head[i]=-,depth[i]=;
tot=,len=;
}
inline void makest(){
for(it i=;i<=len;i++)st[i][]=depth[i];
for(it i=;<<i<=len;i++){
for(it j=;j+(<<i)-<=len;j++){
st[j][i]=min(st[j][i-],st[j+(<<(i-))][i-]);
}
}
}
inline int dis(int u,int v){
int l=first[u],r=first[v];
if(l>r){swap(l,r);}
int k=log2(r-l+);
int dep=min(st[l][k],st[r-(<<k)+][k]);
return dist[u]+dist[v]-*dist[value[first[dep]]];
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init(n);
for(it i=;i<n-;i++){int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
dfs(,,);
makest();
while(m--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",dis(l,r));
}
}
return ;
}

用倍增

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define modd 998244353
const int maxn=4e4+;
struct node{
int v,next,dist;
}a[maxn<<];
int n,m,tot;
int fath[maxn][], depth[maxn];
int dist[maxn],head[maxn];
void add(int u,int v,int dist0){
a[tot].next=head[u];
a[tot].dist=dist0;
a[tot].v=v;
head[u]=tot++;
}
void dfs(int u,int fa,int d) {
fath[u][]=fa; depth[u]=d;
for(int i=;i<;i++) fath[u][i]=fath[fath[u][i-]][i-];
for (int i=head[u];~i;i=a[i].next){
int v=a[i].v;if(v==fa)continue;
dist[v]=dist[u]+a[i].dist;
dfs(v,u,d+);
}
}
void init(int n){
for(int i=;i<=n;i++)fath[i][]=,dist[i]=,head[i]=-,depth[i]=;
tot=;
}
inline int lca(int x,int y){
if(depth[x]<depth[y])swap(x,y);
int h=depth[x]-depth[y];
for(it i=;h>;i++){
if(h&){
x=fath[x][i];
}
h>>=;
}
if(x==y)return x;
for(it i=;i>=;i--){
if(fath[x][i]!=fath[y][i]){
x=fath[x][i];
y=fath[y][i];
}
}
return fath[x][];
}
inline int dis(int u,int v){
int d=lca(u,v);
return dist[u]+dist[v]-*dist[d];
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init(n);
for(it i=;i<n-;i++){int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
dfs(,,);
while(m--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",dis(l,r));
}
}
return ;
}

HDU 2586(LCA欧拉序和st表)的更多相关文章

  1. lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增

    https://www.luogu.org/problemnew/show/P3379 1.欧拉序+rmq(st) /* 在这里,对于一个数,选择最左边的 选择任意一个都可以,[left_index, ...

  2. HDU - 4548-美素数 (欧拉素数筛+打表)

    小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识.  问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为"美素数&quo ...

  3. hdu 2586 欧拉序+rmq 求lca

    题意:求树上任意两点的距离 先说下欧拉序 对这颗树来说 欧拉序为 ABDBEGBACFHFCA 那欧拉序有啥用 这里先说第一个作用 求lca 对于一个欧拉序列,我们要求的两个点在欧拉序中的第一个位置之 ...

  4. 【BZOJ3611】[Heoi2014]大工程 欧拉序+ST表+单调栈

    [BZOJ3611][Heoi2014]大工程 Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶 ...

  5. Bzoj 2286 & Luogu P2495 消耗战(LCA+虚树+欧拉序)

    题面 洛谷 Bzoj 题解 很容易想到$O(nk)$的树形$dp$吧,设$f[i]$表示处理完这$i$颗子树的最小花费,同时再设一个$mi[i]$表示$i$到根节点$1$路径上的距离最小值.于是有: ...

  6. P3379 【模板】最近公共祖先(LCA)(欧拉序+rmq)

    P3379 [模板]最近公共祖先(LCA) 用欧拉序$+rmq$维护的$lca$可以做到$O(nlogn)$预处理,$O(1)$查询 从这里剻个图 #include<iostream> # ...

  7. dfs序和欧拉序

    生命不息,学习不止,昨天学了两个算法,总结一下,然而只是略懂,请路过的大佬多多谅解.   一.dfs序 1.什么是dfs序? 其实完全可以从字面意义上理解,dfs序就是指一棵树被dfs时所经过的节点的 ...

  8. LCA-RMQ+欧拉序

    还是那一道洛谷的板子题来说吧 传送门 其实好几天之前就写了 结果dr实在是太弱了 没有那么多的精力 于是就一直咕咕咕了 哎 今天终于补上来了 LCA概念传送门 RMQ传送门 这个算法是基于RMQ和欧拉 ...

  9. [BZOJ3772]精神污染 主席树上树+欧拉序

    3772: 精神污染 Time Limit: 10 Sec  Memory Limit: 64 MB Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位 ...

随机推荐

  1. arm学习笔记

    学习ARM也有一定时间了,想想还是记点东西,要不以后就忘了.这是我的第一片,简简单单.但比较基础.1. ARM中一些常见英文缩写解释MSB:最高有效位:LSB:最低有效位:AHB:先进的高性能总线:V ...

  2. C语言运算符的优先级与结合性

    结合性:左结合是从左到右依次执行,右结合是从右到左依次执行. 优先级 运算符 名称或作用 运算类型 结合方向 特点 1 () [] -> . 小括号运算符 下标运算符 指向结构成员运算符 结构成 ...

  3. 3_time

    3. Time and order What is order and why is it important? What do you mean "what is order"? ...

  4. [SHOI2016] 黑暗前的幻想乡 - 矩阵树定理,容斥

    #include <bits/stdc++.h> using namespace std; #define int long long const int N = 20; const in ...

  5. C++ 实例练习-替换原生数组

    C++ 实例练习-替换原生数组 main.cpp #include <stdio.h> #include "intarray.h" int main(int argc, ...

  6. 三、ZigBee无线网络工具

    CC2530概述 CC2530是德州仪器Ti公司用于2.4-GHz IEEE 802.15.4.ZigBee 和 RF4CE 应用的一个真正的片上系统(SoC)解决方案,是作为ZigBee无线传 感网 ...

  7. centost redhat 卸载rpm以及yum install 的正确姿势

    先看yum  install 的卸载: 第一列为我们要的包名: 那么要移除必须使用 yum list |grep  collectd | awk '{print $1}' |xargs  yum  r ...

  8. vue.js + element中el-select实现拼音匹配,分词、缩写、多音字匹配能力

    1.既然要用到拼音搜索,我们就需要一个拼音库,在这里我推荐一个第三方包:https://github.com/xmflswood/pinyin-match,在这里首先对这个包的开发者表示万分的感谢. ...

  9. js -- 高阶函数的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. oracle分组并在组内排序

    根据c1,c2分组,并且根据c3排序,取第一行select tt.*  from (select row_number() over(partition by c1, c2 order by c3 d ...