贪心+SPFA——游

来源:互联网 发布:热血江湖源码 编辑:程序博客网 时间:2024/06/08 15:33

问题背景

zhx和他的妹子出去玩。


问题描述

zhx和他的妹子去一个国家旅游,共有N个旅游景点,N-1条双向连接的道
路将它们联通起来,每一条道路有固定长度。一开始zhx位于1号景点。 
现在希望你能够求出旅行长度最小的方案,使得每个景点至少被访问到一次。


输入格式

第一行两个整数N,代表景点数目。 
接下来 N-1行,每行三个整数s,t,w表示有一条从s到t的双向道路,长度为w。s和t的编号从1开始。 


输出格式


1 2 3 
2 3 3 


样例输出


样例输入


1 2 3 
1 3 3


样例输出


数据规模与约定

对于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 100010using 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;}