树上距离(lca)(倍增)

Posted SSL_LKJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树上距离(lca)(倍增)相关的知识,希望对你有一定的参考价值。

树上距离


输入样例

1

2 2 
1 2 100 
1 2 
2 1

2

3 2
1 2 10
3 1 15
1 2
3 2

输出样例

1

100
100

2

10
25

解题思路

lca 模板

倍增优化

AC代码

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,tot,len[20005],head[20005],deep[20005],f[20005][20];
struct node
{
	int to,next,w;
}a[40005];
void add(int x,int y,int z)//建边
{
	a[++tot]=(node){y,head[x],z};
	head[x]=tot;
}
void ycl()//预处理 f数组
{
	for(int j=1;j<16;j++)
	 	for(int i=1;i<=n;i++)
	 		f[i][j]=f[f[i][j-1]][j-1];
}
void dfs(int x,int fa)//深搜
{
	deep[x]=deep[fa]+1;
	f[x][0]=fa;
	for(int i=head[x];i;i=a[i].next)
	{
		if(a[i].to==fa)continue;
		len[a[i].to]=len[x]+a[i].w;
		dfs(a[i].to,x);
	}
}
int lca(int x,int y)//lca求最近公共祖先
{
	if(deep[x]<deep[y])swap(x,y);
	for(int i=15;i>=0;i--)
		if(deep[f[x][i]]>=deep[y])
			x=f[x][i];
	if(x==y)return x;
	for(int i=15;i>=0;i--)
		if(f[x][i]!=f[y][i])
			x=f[x][i],y=f[y][i];
	return f[x][0];
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<n;i++)
	{
		int x,y,k;
		scanf("%d%d%d",&x,&y,&k);
		add(x,y,k); 
		add(y,x,k);
	}
	dfs(1,0);
	ycl();
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		int o=lca(x,y);
		printf("%d\\n",len[x]-len[o]+len[y]-len[o]);//求答案
	}
	return 0;
}

谢谢

以上是关于树上距离(lca)(倍增)的主要内容,如果未能解决你的问题,请参考以下文章

NKOJ P3815 树上的询问 (LCA 倍增)(复习距离倍增)

ybtoj 倍增问题课堂过关LCA例题3树上距离

AHOI2008 紧急集合 树上倍增

BZOJ-4281Zwi?zek Harcerstwa Bajtockiego 树上倍增LCA

倍增法求LCA

FJUT 聪明的商人(树上倍增)题解