(无向)树上的逃和追 ,(有向)树才有所谓深度,(无向)树只有距离最远的节点

本文讨论了一种树结构中寻找距离给定节点最远的叶子节点的问题,指出初始策略中使用Dijkstra算法的不适用性。作者通过分析错误,强调了树的特点——两点间唯一路径,提出正确的解决方案。错误包括:未考虑节点可能向上逃至最远叶子节点,以及错误地使用深度信息。最后,给出了修正后的算法实现,用于计算最大总距离。
摘要由CSDN通过智能技术生成

(无向)树上的逃和追
本 来 想 先 找 到 距 离 x 最 远 的 节 点 y , 再 用 D i j k s t r a 求 1 , y 的 最 短 距 离 ∗ 2 本来想先找到距离x最远的节点y,再用Dijkstra求1,y的最短距离*2 xy,Dijkstra1,y2

真 的 是 昏 了 头 , 树 中 两 个 已 知 节 点 之 间 只 有 一 条 路 , 距 离 是 固 定 的 , 又 不 是 图 真的是昏了头,树中两个已知节点之间只有一条路,距离是固定的,又不是图 ,,

关于非根节点的节点的深度(错误预警)

距离x最远的叶子节点,求的时候犯难了,因为x的father有点难找
要知道一棵树是可以任意指定根节点的,那么原来意义上的根节点将成为后者的某个叶子节点,也就是dfs(x,-1)求x到所有节点的距离d2,通过比较dfs(1,-1)求出的所有节点到根节点的距离d1,比较d2[u]和d1[u]就可以知道节点u是在节点x以上(不能到达)还是以下 (走向叶子节点的方向)
比较所有x以下节点里面的最大值就可以知道距离x最远的叶子节点

当 然 了 , 最 后 的 结 果 就 是 ( m a x ( d 2 [ u ] ) + d 1 [ x ] ) ∗ 2 当然了,最后的结果就是( max(d2[u]) +d1[x] )*2 (max(d2[u])+d1[x])2

1和x之间的距离是固定的,y是距离x最远的节点,固定值+最大值=最大总值
其实就是 2*max(d1[u]), 那为啥还要求d2[u]呢?因为这个u必须要是x可以到达的

至于一开始想的dijkstra,找出了距离x最远的y,1和x距离固定,又是一棵树而不是图,1到y只有一条路呀,距离是固定的!!Dijkstra是求图的单源最短路径呀!

好了,说了这么一大堆,差点就沾沾自喜以为全懂全会了
然后被一个测试点打回原形,非常好🙂

10 4
5 4
8 3
4 6
5 3
7 9
1 3
5 10
2 9
9 8

正确答案

8

错误答案

10

在这里插入图片描述

错误一:x并非只能往下往叶子节点的方向逃,如果可以,他会先向上走,再向下走到距离根节点最远的叶子节点(当然了,如果距离根节点最远的节点就在x的分枝下面,自然皆大欢喜),所以这才是比较 d 1 [ u ] 和 d 2 [ u ] d1[u]和d2[u] d1[u]d2[u]的真正意义所在,而不是通过比较说明u在x节点的下面,在上面也行呀,只消距离1比距离x远,比如图中节点5之于节点1、之于节点4
错误二:所以 d 1 [ u ] > d 2 [ u ] d1[u] > d2[u] d1[u]>d2[u],并不能说明u节点位于x的下方,所以要求x往下可以走到的最远的叶子节点(节点x的深度)

感觉用链式前向星来存储无向图求深度,woc,树的边是有向的呀,如果链式前向星存储有向图,求某节点的深度就很ok了
存储的是无向树,那么所谓的深度,就是距离该节点最远的点了

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
struct edge{
	int to,nex;
}e[N<<1];
int head[N];
int cnt=0;
void add(int u,int v){
	e[++cnt].to=v;
	e[cnt].nex=head[u];
	head[u]=cnt;
}
int d1[N];
int d2[N];
void dfs(int u,int fa,int d[]){
	for(int i=head[u];i;i=e[i].nex){
		int to=e[i].to;
		if(to==fa)continue;
		d[to]=d[u]+1;
		dfs(to,u,d);
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,x;
	cin>>n>>x;
	int u,v;
	for(int i=1;i<n;i++){
		cin>>u>>v;
		add(u,v);
		add(v,u);
	} 
	fill(d1,d1+N,-1);//
	fill(d2,d2+N,-1);//初始化为-1也没用,以x为根节点,所有节点都可到达,都会有个具体距离 
	d1[1]=0;
	d2[x]=0;
	dfs(1,0,d1);
	dfs(x,0,d2);//把数组当参数传进去省得写两个dfs噢 
	int maxx=-1;
	for(int i=1;i<=n;i++){
	if(d1[i]>d2[i])maxx=max(maxx,d1[i]);
//	if(d1[i]>d2[i])maxx=max(maxx,d1[x]+d2[i]);//可能会偏大,1会采取最优策略到i,不会先到x再绕道i 
	}
	cout<<maxx*2;
//	cout<<endl;
//	for(int i=1;i<=n;i++){
//	if(d2[i]!=-1&&d1[i]>d2[i]){
//		cout<<i<<" "<<d1[i]<<" "<<d2[i]<<endl; 
//	}
//	}

	return 0;
} 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值