题意
Shapur 决定到波斯的 n n n 个城市去寻找可以使用的最好的山,但是战斗后他太累了,所以不想走太多的路。因此,他希望以最短的路径走遍所有的 n n n 个城市。某些城市以双向道路相连,一共有 n − 1 n - 1 n−1 条双向道路。你可以通过这些道路从一个城市到另一个城市。在两个城市间最多只有一条双向道路。所有城市被从 1 1 1 到 n n n 编号。
Shapur 目前在城市 1 1 1,他想以最短的路径访问所有其他城市。他可以在任何城市结束他的旅行。
帮助 Shapur 算出他最少要走多远的路。
思路
由
n
−
1
n-1
n−1 条边可以很容易的想到这是一棵树。我们先考虑最后一定要返回起点的情况。显而易见,每条边都要经过两次,一次来一次回去。因此,
a
n
s
←
2
×
∑
i
=
1
n
w
i
ans \gets 2 \times \sum_{i = 1}^{n} w_i
ans←2×∑i=1nwi。
因为我们可以停在任意点,因此有一段路程就可以不用走。假设我们停在途中的点
5
5
5,则就省下了
4
+
5
=
9
4 + 5 = 9
4+5=9 的长度。因为
a
n
s
ans
ans 要尽可能小,所以这个长度要尽可能大。当这个长度最大时,显而易见,我们找的就是一条最长链,用 DFS
即可解决。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct edge{
int to,w;
}e[200005];
int ans = 0,ans1 = 0;
int head[200005],nex[200005],cnt = 0,n,x[100005],y[100005],z[100005];
void add(int f,int t,int w) {
nex[++cnt] = head[f];
head[f] = cnt;
e[cnt].to = t;
e[cnt].w = w;
ans += w;
}
void dfs(int x,int fa,int min_ans) {
//printf("%lld %lld\n",x,min_ans);
ans1 = max(ans1,min_ans);
for(int i = head[x];x;i = nex[x]) {
if(e[i].to != fa) {
dfs(e[i].to,x,min_ans + e[i].w);
}
}
return;
}
signed main() {
scanf("%lld",&n);
for(int i = 1;i < n;i++) {
scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
add(x[i],y[i],z[i]),add(y[i],x[i],z[i]);
}
dfs(1,0,0);
printf("%lld\n",ans - ans1);
return 0;
}