题目描述
很久以前,T 王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T 国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J 是 T 国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了 J 最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
聪明的 J 发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第 x−1 千米到第 x 千米这一千米中(xx 是整数),他花费的路费是 x+10 这么多。也就是说走 1千米花费 11,走 2 千米要花费 23。
J 大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入格式
输入的第一行包含一个整数 n(n≤1e5),表示包括首都在内的 T 王国的城市数。
城市从 1 开始依次编号,1 号城市为首都。
接下来 n−1 行,描述 T 国的高速路(T 国的高速路一定是 n−1 条)。
每行三个整数 Pi,Q,Di,表示城市 Pi 和城市 Qi 之间有一条高速路,长度为 Di(Di≤1000)米。
输出格式
输出一个整数,表示大臣J最多花费的路费是多少。
输入输出样例
输入
5 1 2 2 1 3 1 2 4 5 2 5 4
输出
135
思路:
由题目“如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。”可知,所有的城市连起来就是一棵树,本题就是要求树的直径,即最大距离,然后根据距离和路费的关系得出答案。
求树的直径的步骤:
-
任取一点 x ;
-
找到距离 x 最远的点 y ;
-
从 y 开始遍历,找到离 y 最远的点,与 y 最远的点的距离是树的直径。
#include <bits/stdc++.h>
#define ll long long
#define endl "\n"
using namespace std;
//ll w[100005][10005]; 邻接矩阵会爆
struct edge
{
ll city,w;
};
//邻接表
vector<edge> h[100005];//定义的是一个含有 100005 个 std::vector<edge> 类型元素的数组
int dist[100005];//存放当前节点的最大距离
void dfs(int u,int father, int dis)
{
dist[u]=dis;
for(int i=0;i<h[u].size();i++) {
if(h[u][i].city!=father) {
dfs(h[u][i].city,u,dis+h[u][i].w);
}
}
}
int main()
{
ll n,ans=0;
cin>>n;
for(int i=0;i<n-1;i++)
{
int p,q,d;
cin>>p>>q>>d;
h[p].push_back({q,d});
h[q].push_back({p,d});
}
dfs(1,-1,0);//任一点开始dfs
int u=1;
for(int i=1;i<=n;i++)
{
if(dist[i]>dist[u])
{
u=i;//找到与当前点距离最远的一个点(即树的直径的一个端点)
}
}
dfs(u,-1,0);//再找到树的直径的端点能到达的所有点
for(int i=1;i<=n;i++)
{
if(dist[i]>dist[u])
{
u=i;//找到最远的那个点,就找到了当前树的直径的另一个端点
}
}
int r=dist[u];//树的直径
ans=r*10+r*(1+(r))/2;
cout<<ans<<endl;
return 0;
}