1.原题和原题链接
U392706 【模板】树的中心
题目背景
树的中心定义为:一个节点作为整棵树的根节点时,深度最大的节点的深度最小,则该节点是树的中心。
注意,树的中心不一定唯一。
题目描述
给定一棵 n n n 个节点的树,求树的所有中心。
输入格式
第一行一个整数 n n n。
接下来 n − 1 n-1 n−1 行每行三个整数: x , y , z x,y,z x,y,z,表示存在一条边 ( x , y ) (x,y) (x,y),边权为 z z z。
输出格式
若干行,每行一个整数,表示所有树的中心的节点编号,从小到大排序。
输入输出样例 #1
输入 #1
10
1 2 3
1 3 4
2 4 5
2 5 7
5 6 6
5 7 5
6 9 9
6 10 1
7 8 2
输出 #1
5
输入输出样例 #2
输入 #2
5
1 2 4
1 3 0
2 4 0
1 5 4
输出 #2
1
3
说明/提示
1 ≤ n , x , y ≤ 10 6 , z ≤ 10 9 1\le n,x,y\le 10^6,z\le 10^9 1≤n,x,y≤106,z≤109。
2.主要思路
这是一道找树中心的模板题,我们可以使用两次dfs搞定。
第一次dfs从根节点出发,对每个节点计算两个值:d1是它向下走能到的最远距离,d2是第二远的距离,顺便记录下d1对应的子节点p。
第二次dfs就用来计算每个节点向上走的最远距离up。如果当前节点是父节点d1路径上的,那父节点能提供的最大距离就是d2[父节点]和up[父节点]里的最大值加上边权;不然就是d1[父节点]和up[父节点]里的最大值加上边权。
最后每个节点的最远距离就是d1和up里的最大值,找最小的那个最大值对应的节点,排序输出就行了。
3.AC代码
#include<bits/stdc++.h>
using namespace std;
int n,d1[1000005],d2[1000005],up[1000005],p[1000005];
int ans[1000005],s;
vector<pair<int,int>> g[1000005];
void dfs1(int k,int fa){
for(int i=0;i<g[k].size();i++){
int v=g[k][i].first;
int w=g[k][i].second;
if(v==fa) continue;
dfs1(v,k);
int x=d1[v]+w;
if(x>d1[k]){
d2[k]=d1[k];
d1[k]=x;p[k]=v;
}
else if(x>d2[k]) d2[k]=x;
}
}
void dfs2(int k,int fa){
for(int i=0;i<g[k].size();i++){
int v=g[k][i].first;
int w=g[k][i].second;
if(v==fa) continue;
if(p[k]==v){
up[v]=max(d2[k],up[k])+w;
}
else{
up[v]=max(d1[k],up[k])+w;
}
dfs2(v,k);
}
}
int main(){
cin>>n;
for(int i=1;i<n;i++){
int k,v,w;
cin>>k>>v>>w;
g[k].push_back({v,w});
g[v].push_back({k,w});
}
dfs1(1,0);dfs2(1,0);
int mh=(1<<30);
for(int i=1;i<=n;i++){
mh=min(mh,max(d1[i],up[i]));
}
s=1;
for(int i=1;i<=n;i++){
if(max(d1[i],up[i])==mh){
ans[s]=i;s+=1;
}
}
sort(ans+1,ans+s);
for(int i=1;i<s;i++) cout<<ans[i]<<endl;
return 0;
}
以上就是本篇全部内容,感谢浏览!
58

被折叠的 条评论
为什么被折叠?



