[LCA 树上最短路 BFS] 距离
Posted 鱼竿钓鱼干
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LCA 树上最短路 BFS] 距离相关的知识,希望对你有一定的参考价值。
[LCA 树上最短路] 距离
题目
添加链接描述题目链接
思路
多次询问树上最短路。
多次询问最短路考虑floyd,发现必然T,然后考虑题目特点,是要求树上的最短路。
树上两点路径是唯一的,所以只需要计算两点之间距离就可以了。
考虑使用LCA优化
定义dist[i]为节点i到根节点距离
a
n
s
=
a
b
s
(
d
i
s
t
[
x
]
−
d
i
s
t
[
l
c
a
]
)
+
a
b
s
(
d
i
s
t
[
y
]
−
d
i
s
t
[
l
c
a
]
)
ans=abs(dist[x]-dist[lca])+abs(dist[y]-dist[lca])
ans=abs(dist[x]−dist[lca])+abs(dist[y]−dist[lca])
然后就是代码实现,原本尝试用vector存图+dfs维护深度和到根节点距离
但是发现,深度很容易维护,到根节点距离维护是比较复杂的,遍历要找到这个点的来源。
对于需要快速确定来源这一操作,我们可以考虑用bfs代替原本的dfs
另外太久没写vetor了,犯了一个憨憨错误,vector下标操作只能索引已经存在的值(要么都初始化为0),否则会报错
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10,M=25;
struct Node{
int p,w;
};
vector<Node>root[N];
int n,m,st,cnt;
int fa[N][M],dep[N],dist[N];
int LG[N];
void prework(){
LG[1]=0;
for(int i=2;i<=N;i++)LG[i]=LG[i/2]+1;
}
bool vis[N];
void bfs(){
queue<int>q;
q.push(1);dep[1]=1;vis[1]=true;
while(q.size()){
int x=q.front();q.pop();
for(auto to:root[x]){
int y=to.p,edge=to.w;
if(vis[y])continue;
vis[y]=true;
dep[y]=dep[x]+1;
dist[y]=dist[x]+edge;
fa[y][0]=x;
for(int i=1;i<=20;i++)
fa[y][i]=fa[fa[y][i-1]][i-1];
q.push(y);
}
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])swap(x,y);
while(dep[x]>dep[y])
x=fa[x][LG[dep[x]-dep[y]]];
if(x==y)return y;
for(int i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main(){
prework();
cin>>n>>m;
for(int i=1;i<n;i++){
int x,y,k;cin>>x>>y>>k;
root[x].push_back({y,k});
root[y].push_back({x,k});
}
bfs();
while(m--){
int x,y;cin>>x>>y;
int lca=LCA(x,y);
cout<<abs(dist[x]-dist[lca])+abs(dist[y]-dist[lca])<<endl;
}
return 0;
}
以上是关于[LCA 树上最短路 BFS] 距离的主要内容,如果未能解决你的问题,请参考以下文章