python手机版/网站优化效果
题目链接:https://www.acwing.com/problem/content/1209/
题目
很久以前,T王国空前繁荣。
为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。
同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J是T国重要大臣,他巡查于各大城市之间,体察民情。
所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。
他有一个钱袋,用于存放往来城市间的路费。
聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第xxx千米到第x+1x+1x+1千米这一千米中(xxx是整数),他花费的路费是x+10x+10x+10这么多。也就是说走111千米花费111111,走222千米要花费232323。
J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入格式
输入的第一行包含一个整数 nnn,表示包括首都在内的T王国的城市数。
城市从 111 开始依次编号,111 号城市为首都。
接下来 n−1n−1n−1 行,描述T国的高速路(T国的高速路一定是 n−1n−1n−1 条)。
每行三个整数 PiP_iPi,QiQ_iQi,DiD_iDi,表示城市 PiP_iPi 和城市 QiQ_iQi 之间有一条双向高速路,长度为 DiD_iDi 千米。
输出格式
输出一个整数,表示大臣J最多花费的路费是多少。
数据范围
1≤n≤1051≤n≤10^51≤n≤105,
1≤Pi,Qi≤n1≤P_i,Q_i≤n1≤Pi,Qi≤n,
1≤Di≤10001≤D_i≤10001≤Di≤1000
输入样例:
5
1 2 2
1 3 1
2 4 5
2 5 4
输出样例:
135
思路:由于题目说到不重复经过大城市,从首都到达每个大城市的方案都是唯一的。因此可以知道该图是一棵树,本题求的是树的直径
树的直径:
树中长度最长的路径
怎么找树的直径
1、任取一点xxx
2、找到距离xxx最远的点yyy
3、从yyy开始遍历,找到离yyy最远的点,与yyy最远的点的距离是树的直径
证明:
yyy一定是树的直径的端点
假设yyy不是树的直径的端点,分两种情况,如图所示,其中UVUVUV是树的直径
情况1:
xyxyxy与UVUVUV有交点,由于离xxx最远的点是yyy,因此
有1+3<=3+4有1 + 3 <= 3 + 4有1+3<=3+4
即3<=4即 3 <= 4即3<=4
则3+2<=4+2则 3 + 2 <= 4 + 2则3+2<=4+2
由于 3+23 + 23+2是树的直径,因此4+24 + 24+2一定是树的直径,因此y不是树的直径的端点矛盾
情况2:
xyxyxy与UVUVUV没有交点,由于离xxx最远的点是yyy,因此
有1+2>=1+3+5有 1 + 2 >= 1 + 3 + 5有1+2>=1+3+5
即2>=3+5即 2 >= 3 + 5即2>=3+5
即2>5即 2 > 5即2>5
则2+3>5则 2 + 3 > 5则2+3>5
则2+3+5>4+5则 2 + 3 + 5 > 4 + 5则2+3+5>4+5
由于 4+54 + 54+5是树的直径,但存在着一个长度更长的路径,因此yyy不是树的直径的端点矛盾
因此,yyy一定是树的直径的端点
AC代码
#include <iostream>
#include <cstdio>
#include <vector>using namespace std;const int N = 100010;int n;struct Edge
{int id;int w;
};vector<Edge> h[N];
int dist[N];void dfs(int u,int father,int distance)
{dist[u] = distance;for(int i = 0; i < h[u].size(); i++)if(h[u][i].id != father)dfs(h[u][i].id,u,dist[u] + h[u][i].w);
}int main()
{scanf("%d",&n);for(int i = 0; i < n - 1; i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);h[a].push_back({b,c});h[b].push_back({a,c});}dfs(1,-1,0);int u = 1;for(int i = 1; i <= n; i++ )if(dist[i] > dist[u]) u = i;dfs(u,-1,0);for(int i = 1; i <= n; i++)if(dist[i] > dist[u]) u = i;int s = dist[u];printf("%lld\n",s*11+s*(s-1ll)/2); // 1ll转成 long long 来计算return 0;
}