大臣的旅费——第四届蓝桥杯省赛C语言A组第10题

来源:互联网 发布:java线程死锁例子 编辑:程序博客网 时间:2024/06/06 14:10

问题描述


很久以前,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


输出格式

大臣J从城市4到城市5要花费135的路费。


解题思路:

该题是要求树的直径,即一个树的最长简单路。

直径的求法:两遍DFS (or BFS)

任选一点u为起点,对树进行DFS遍历,找出离u最远的点v;

以v为起点,再进行DFS遍历,找出离v最远的点w。则v到w的路径长度即为树的直径。

原问题可以在O(E)时间内求出


证明:对于任意点u,距离它最远的点v一定是最长路的一端。

如果u在最长路上,那么v一定是最长路的一端。可以用反证法:假设v不是最长路的一端,则存在另一点v’使得(u→v’)是最长路的

部分,于是len(u→v’) > len(u→v)。但这与条件“v是距u最远的点”矛盾。

如果u不在最长路上,则u到其距最远点v的路与最长路一定有一交点c,且(c→v)与最长路的后半段重合,即v一定是最长路的一端。


参考奇老师的代码:

#include<iostream>#include<vector>#include<utility>#include<queue>#include<cstring>#include<cstdio>using namespace std;#define INF 1000000009const int  N=1000005;vector<pair<int,int> > G[N];bool visit[N];int d[N];void init(){    memset(visit,0,sizeof(visit));}void dfs(int u){    visit[u]=1;    int size=G[u].size();    for(int i=0; i<size; i++)    {        int v=G[u][i].first;        if(!visit[v])        {            d[v]=d[u]+G[u][i].second;            dfs(v);        }    }}int main(){    int n;    cin>>n;    int u,v,w;    for(int i=0; i<n-1; i++)//注意是n-1行数据    {        scanf("%d%d%d",&u,&v,&w);        G[u-1].push_back(make_pair(v-1,w));        G[v-1].push_back(make_pair(u-1,w));    }    //第一遍    init();    for(int i=0; i<n; i++)        d[i]=(i==0?0:INF);    dfs(0);    int start=0;    int max=-1;    for(int i=0; i<n; i++)        if(d[i]>max&&d[i]!=INF)        {            max=d[i];            start=i;        }    //第二遍    init();    for(int i=0; i<n; i++)        d[i]=(i==start?0:INF);    dfs(start);    int ans=-1;    for(int i=0; i<n; i++)    {        if(d[i]>ans && d[i]!=INF)            ans=d[i];    }    ans=10*ans+ans*(ans+1)/2;    cout<<ans<<endl;    return 0;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 太阳晒出胳膊上长斑怎么办 宇航员在太空死后怎么办 太阳暴晒起的斑怎么办 太阳晒出来的斑怎么办 被认定D级危房怎么办 突然发现两个关系遥远怎么办 如果没有地球人类会怎么办 小锅盖被屏蔽了怎么办 美的冰箱故障通讯不合格怎么办 美的冰箱通讯不合格怎么办 文明6金币降到0怎么办 紫癜肾炎长期尿潜血怎么办 肾移植后血压高怎么办 尿道长了个肿瘤怎么办 吃了有病的鹅怎么办 狗狗得了乳腺瘤怎么办 孕28周还是臀位怎么办 怀孕五个月胎位不正怎么办 33周了胎位不正怎么办 足月胎儿不足5斤怎么办 绒癌观察期怀孕怎么办 宝宝囱门闭合晚怎么办 慢性硬脑膜下血肿复发怎么办 佝偻病导致囟门晚闭怎么办 儿童液体补多了怎么办 脑脊液鼻漏3年了怎么办 结石掉到膀胱里怎么办 肾结石引起的腰疼怎么办 肾结石小但很疼怎么办 狗狗得了尿结石怎么办 生理期第四天必须游泳怎么办 碎石后吐的厉害怎么办 白细胞高红细胞高血尿怎么办? 早期肾癌术后复发该怎么办 肾结石因运动引起尿血怎么办 宝宝大便镜检阳性潜血怎么办 尿不尽刺痛带血怎么办 狗狗拉肚子拉血怎么办 肾血肿怎么办才吸收快 体检尿蛋白高3怎么办 肾炎会引起脸肿怎么办