洛谷U392706 【模板】树的中心题解

1.原题和原题链接

原题链接

U392706 【模板】树的中心

题目背景

树的中心定义为:一个节点作为整棵树的根节点时,深度最大的节点的深度最小,则该节点是树的中心。

注意,树的中心不一定唯一。

题目描述

给定一棵 n n n 个节点的树,求树的所有中心。

输入格式

第一行一个整数 n n n

接下来 n − 1 n-1 n1 行每行三个整数: 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 1n,x,y106,z109

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;
}

以上就是本篇全部内容,感谢浏览!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值