问题描述
很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。
J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入格式
输入的第一行包含一个整数n,表示包括首都在内的T王国的城市数
城市从1开始依次编号,1号城市为首都。
接下来n-1行,描述T国的高速路(T国的高速路一定是n-1条)
每行三个整数Pi, Qi, Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。
输出格式
输出一个整数,表示大臣J最多花费的路费是多少。
样例输入1
5
1 2 2
1 3 1
2 4 5
2 5 4
样例输出1
135
刷了一段时间蓝桥杯这是第一个有点算法思想的东西。。。
思路:这里也是看不可能存在回路啥的,蓝桥杯怎么可能那么难。。。果断是树的问题,最长的距离,不就是树的最大直径吗?
经典的想法,先任意一个点搜索,找到最远的一个点必定是直径上的一个点,然后再从这个点搜一遍就是直径。
在我的程序里用了一些取巧的东西,都注释了。我使用vec数组构建有向双向树做的,然后有个map数组离散化了一下:
#include<bits/stdc++.h>
#define input freopen("input.txt","r",stdin)
using namespace std;
vector<int>vec[100002];
map<long long,long long>mp; //这里猜测数据不会太大,为了方便记录两点的距离,用map构造value1*1e9+value2的结构离散化
int v[100002],maxx,maxpoint;
void dfs(int pos,int sum){ //pos表示当前的位置,sum表示从开头到当前位置距离
int flag=0; //flag用来控制结束,当这个点没法走的时候说明到了除了出发点外的某一叶子结点
for(int i=0;i<vec[pos].size();i++){
if(v[vec[pos][i]]==0){
flag=1; //表示当前点有能走的点
v[vec[pos][i]]=1; //搜索前要标记
dfs(vec[pos][i],sum+mp[pos*(long long)1e9+vec[pos][i]]);
}
}
if(flag==0){
if(maxx<sum){ //只有当此解是最优解时更新状态值
maxx=sum;
maxpoint=pos;
}
return ;
}
}
int main(){
int n,temp1,temp2,key;
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=100000;i++){
vec[i].clear();
}
mp.clear();
for(int i=1;i<n;i++){
scanf("%d%d%d",&temp1,&temp2,&key);
vec[temp1].push_back(temp2);
vec[temp2].push_back(temp1);
mp[temp1*(long long)1e9+temp2]=key;
mp[temp2*(long long)1e9+temp1]=key;
}
maxx=0; //maxx表示从起点到叶子节点的最大值
maxpoint=0; //maxpoint表示从开始节点到哪个叶子节点是最好的
memset(v,0,sizeof(v)); //每次开始初始化v状态
v[1]=1; //起点标记
dfs(1,0);
int start=maxpoint;
maxx=0;
maxpoint=0;
memset(v,0,sizeof(v));
v[start]=1;
dfs(start,0);
cout<<(long long)((1+maxx)*maxx/2+10*maxx)<<endl;
}
return 0;
}