蓝桥杯 大臣的旅费 By Assassin 树的最大直径

问题描述

很久以前,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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值