(无向)树上的逃和追
本
来
想
先
找
到
距
离
x
最
远
的
节
点
y
,
再
用
D
i
j
k
s
t
r
a
求
1
,
y
的
最
短
距
离
∗
2
本来想先找到距离x最远的节点y,再用Dijkstra求1,y的最短距离*2
本来想先找到距离x最远的节点y,再用Dijkstra求1,y的最短距离∗2
真 的 是 昏 了 头 , 树 中 两 个 已 知 节 点 之 间 只 有 一 条 路 , 距 离 是 固 定 的 , 又 不 是 图 真的是昏了头,树中两个已知节点之间只有一条路,距离是固定的,又不是图 真的是昏了头,树中两个已知节点之间只有一条路,距离是固定的,又不是图
关于非根节点的节点的深度(错误预警)
距离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;
}