树的直径 —— 即一棵树的最长路 附题(大臣的旅费 by蓝桥杯)
来源:互联网 发布:kt交易师软件下载 编辑:程序博客网 时间:2024/06/06 08:38
直接上求法:两遍bfs就可以求得最长路的两个端点。
参考结论:从任意一点出发能搜到的最远的点一定是最长路两个端点中的一个。
(注意:最远可以是权值最远,也可以是边数最多,总之思想是相通的,求法也一样)
证明如下:
首先,设a -- b 是最长路
① 设点u为最长路a -- b上的一个点,所以从该点出发,所能到达的最远的点肯定是a,b之一。
② 设点u不是最长路a -- b上的一点,这里还有一个小结论,就是u到所能到达的最远的点v肯定会与该树的最长路相交,在这先设一个点t为最长路a -- b上的一点且该点是u到最远点路径与a -- b最长路的交点,所以很容易想到了,再假如 a是u到达最远的点。
d[u -- v] = d[u -- t] + d[t -- a].
反证法证明:如果u到最远点v与a--b无交点,即 dis[u -- v] >d[u -- t] + d[t -- a].
d[u -- v] + d[u -- t] + d[t -- b] > d[u -- t] + d[t -- a] + d[t -- b] (== d[a -- b]); 此时与最长路是a -- b相矛盾,反证成功。
在下面附上往年的一道蓝桥杯题目——大臣的旅费
很久以前,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 2 2
1 3 1
2 4 5
2 5 4
大臣J从城市4到城市5要花费135的路费。
下面贴代码:
#include <iostream>#include <cstring>#include <cstdio>#include <queue>using namespace std;struct node{int u, v, w, next;}e, edge[1000005];int head[100005], book[100005];int n, no;void init(){no = 1;for(int i = 1; i <= n; ++i) {head[i] = -1;book[i] = 0;}}void add(int u, int v, int w){//使用前向星来存储边的信息edge[no].u = u;edge[no].v = v;edge[no].w = w;edge[no].next = head[u];head[u] = no++;}int bfs(int x, long long &sum){int k, ans, max, va;max = 0;memset(book ,0, sizeof book);queue<node> q;e.v = x;e.w = 0;q.push(e);while(!q.empty()){//通过队列不断更新,最大的距离,并记录当时的点e = q.front();q.pop();if(book[e.v]) continue;if(max < e.w){max = e.w;ans = e.v;}va = e.w;book[e.v] = 1;k = head[e.v];while(k != -1){if(book[edge[k].v] == 0){e.w = va+edge[k].w;//用出队的权值+该点所能抵达的点的权值e.v = edge[k].v;e.u = edge[k].u;q.push(e);}k = edge[k].next;}}sum = max;return ans;}int main(){int i, u, v, w, a, b, ans;long long sum;cin >> n;init();for(i = 1; i < n; ++i){cin >> u >> v >> w;add(u, v, w);add(v, u, w);}if(n == 1) printf("0\n");else{sum = 0;a = bfs(1, sum);//两次bfs获取最长路两端点,并用sum作为输出参数获得最长路的大小sum = 0;b = bfs(a, sum);printf("%lld\n", sum*10+sum*(sum+1)/2);}return 0;}
继续加油~
- 树的直径 —— 即一棵树的最长路 附题(大臣的旅费 by蓝桥杯)
- 蓝桥杯 大臣的旅费 By Assassin 树的最大直径
- 大臣的旅费(树的直径)
- 大臣的旅费____树的直径
- 蓝桥杯—大臣的旅费
- 蓝桥杯—大臣的旅费
- 蓝桥杯——大臣的旅费(树的最大直径)
- 蓝桥杯-- 历届试题 大臣的旅费(树的直径)
- (水)大臣的旅费 蓝桥杯 树的直径
- 蓝桥杯 大臣的旅费 (求树的直径)
- 蓝桥杯 大臣的旅费 (树的直径)
- 蓝桥杯 大臣的旅费(树的直径 dijkstra,dfs)
- 蓝桥杯历届试题——大臣的旅费(图的最长路)
- 蓝桥杯 大臣的旅费
- 大臣的旅费 - 蓝桥杯
- 蓝桥杯 大臣的旅费
- 大臣的旅费 蓝桥杯
- 蓝桥杯 大臣的旅费
- 【HDU 2098】 分拆素数和 (~水)
- 随机森林(Random Forest)入门与实战
- Android线程间通信机制
- Python实用文本操作
- Codeforces Round #401 (Div. 2)C. Alyona and Spreadsheet(暴暴暴力)
- 树的直径 —— 即一棵树的最长路 附题(大臣的旅费 by蓝桥杯)
- PAT甲级1026. Table Tennis (30)
- struts2:二
- 每日一省之————加权无向图的最小生成树算法(Prim/Kruskal算法)
- 1067. Sort with Swap(0,*) 解析
- 第58篇老师端私有白板展示(一)老师端详细建私有白板及PHP array_reverse 周一
- 统计对象中有几个属性
- Readonly和Disabled的区别
- babel总结