题面
题目描述
很久以前,T 王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T 国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J 是 T 国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了 J 最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
聪明的 J 发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第 x - 1 千米到第 x 千米这一千米中(x 是整数),他花费的路费是 x+10 这么多。也就是说走 1 千米花费 11,走 2 千米要花费 23。
J 大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入格式
输入的第一行包含一个整数 ,表示包括首都在内的 T 王国的城市数。
城市从 1 开始依次编号,1 号城市为首都。
接下来 n-1 行,描述 T 国的高速路(T 国的高速路一定是 n-1 条)。
每行三个整数 ,表示城市 和城市 之间有一条高速路,长度为 千米。
输出格式
输出一个整数,表示大臣J最多花费的路费是多少。
样例 #1
样例输入 #1
5
1 2 2
1 3 1
2 4 5
2 5 4
样例输出 #1
135
提示
样例解释:大臣 J 从城市 4 到城市 5 要花费 135 的路费。
时限 5 秒, 64M。蓝桥杯 2013 年第四届省赛
题目大意
给定一棵树以及其边权,求其树的直径。
思路
从求大臣最大花费中可看出此题是求树的直径。
求树的直径的步骤:
- 求出距离根最远的节点
- 求距离该节点最远的节点
- 求出这两个节点的距离
由题意得,如果大臣走了 x 千米,那么所需费用为,化简得,后面的等差数列可以化为,所以答案为。
或者用二次函数,不难发现 ,该二次函数的对称轴在上,则答案为。
我们可以用深搜与邻接表求出答案。
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int head[N],Next[N*2],ver[N*2],edge[N*2],tot;//邻接表
void add(int x,int y,int z)
{
ver[++tot]=y;edge[tot]=z;
Next[tot]=head[x];head[x]=tot;
}
int n,v[N];
int d[N];//记录距离
void dis(int x,int far)//计算每个点到起点的距离
{//x 表示当前遍历到的点,far 表示从起点到 x 的距离
d[x]=far;
v[x]=1;//被遍历过
for(int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if(v[y]==1)//防止遍历多次
continue;
dis(y,far+z);
}
}
int main()
{
scanf("%d",&n);//可爱的读入
for(int i=1;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
dis(1,0);//以 1 为起点
int far=1;
for(int i=1;i<=n;i++)//离 1 最远的点
if(d[i]>d[far])
far=i;
memset(v,0,sizeof(v));//重置标记数组
dis(far,0);//以 far 为起点
for(int i=1;i<=n;i++)//离 far 最远的点
if(d[i]>d[far])
far=i;
int f=d[far];
printf("%lld",10*f+(1+f)*f/2);//long long 防止爆掉
return 0;//好孩子的好习惯
}
求赞