问题背景
zhx和他的妹子出去玩。
问题描述
zhx和他的妹子去一个国家旅游,共有N个旅游景点,N-1条双向连接的道路将它们联通起来,每一条道路有固定长度。一开始zhx位于1号景点。
现在希望你能够求出旅行长度最小的方案,使得每个景点至少被访问到一次。
输入格式
第一行两个整数N,代表景点数目。接下来 N-1行,每行三个整数s,t,w表示有一条从s到t的双向道路,长度为w。s和t的编号从1开始。
输出格式
31 2 3
2 3 3
样例输出
6
样例输入
31 2 3
1 3 3
样例输出
9
数据规模与约定
对于30%的数据,1≤N≤10。对于70%的数据,1 ≤ N ≤ 1000。
对于100%的数据,1≤N≤50000,1≤w≤1000。
一行一个整数,代表能够访问每个景点至少一次的方案的最小旅行长度。
思路
画图(如下图)可知:
最小旅行长度=树上所有边总长度*2-距离1号节点最远的节点距1号节点的距离
[求点距1号节点的距离可用SPFA]
代码(C++)
#include <queue>
#include <cstdio>
#include <bitset>
#define N 50010
#define M 100010
using namespace std;
int n,u,v,w,pos,he[N],en[M],ne[M],len[M],cnt=0;
long long ans=0,m=0,dis[50010];
const long long inf=9223372036854775807ll;
bitset<N> in; queue<int> q;
inline void add();
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;++i)
scanf("%d%d%d",&u,&v,&w),add(),
ans+=2*w,dis[i]=inf;
q.push(1); in[1]=1;
while(!q.empty())
{
pos=q.front(); q.pop(); in[pos]=0;
for(int k=he[pos];k;k=ne[k])
if(dis[pos]+len[k]<dis[en[k]])
{
dis[en[k]]=dis[pos]+len[k];
if(!in[en[k]])
in[en[k]]=1,q.push(en[k]);
}
}
for(int i=1;i<=n;++i)
if(dis[i]>m)
m=dis[i];
printf("%lld",ans-m);
return 0;
}
inline void add()
{
en[++cnt]=v; len[cnt]=w;
ne[cnt]=he[u]; he[u]=cnt;
en[++cnt]=u; len[cnt]=w;
ne[cnt]=he[v]; he[v]=cnt;
}