链接 : http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1267
添加n-1条边使得图联通,并且权值最大,添加的边的权值是原图中最短路。
首先找出树中的最长路,就是直径,可以dfs两次,任选一个节点,找到它的最远节点u,,再dfs找到u的最远节点v,u----v便是最长路,然后对于剩下的节点,选择离u,v中最远的加入到答案中即可,因为如果存在一条到其他点比到u或v还要长的路,且是在树型结构中,与u,v是树的直径矛盾,所以不可能。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <set>
#include <queue>
using namespace std;
typedef long long ll;
const int INF=1e9+10;
const double EPS = 1e-10;
const ll mod=1e9+7;
typedef pair<int,int> P;
vector<P> g[100005];
ll mx;
void dfs1(int u,int pre,ll dis,int &x){
if(g[u].size()==1&&pre!=-1){
if(mx<dis){
x=u;
mx=dis;
}
return;
}
for(int i=0;i<g[u].size();i++){
int v=g[u][i].first,w=g[u][i].second;
if(v==pre) continue;
dfs1(v,u,1LL*dis+w,x);
}
}
ll diss[100005],dist[100005];
void dfs2(int u,ll pre,ll *dis){
if(g[u].size()==1&&pre!=-1){
return;
}
for(int i=0;i<g[u].size();i++){
int v=g[u][i].first,w=g[u][i].second;
if(v==pre) continue;
dis[v]=1LL*dis[u]+w;
dfs2(v,u,dis);
}
}
int main(){
//freopen("out.txt","w",stdout);
// ios_base::sync_with_stdio(0);
int n;
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++) g[i].clear();
int u,v,w;
for(int i=0;i<n-1;i++){
scanf("%d %d %d",&u,&v,&w);
g[u].push_back(make_pair(v,w));
g[v].push_back(make_pair(u,w));
}
int s,t;
mx=0;
dfs1(1,-1,0,s);
mx=0;
dfs1(s,-1,0,t);
memset(dist,0,sizeof(dist));
memset(diss,0,sizeof(diss));
dfs2(s,-1,diss);
dfs2(t,-1,dist);
ll ans=mx;
for(int i=1;i<=n;i++){
if(i!=s&&i!=t){
ans+=max(dist[i],diss[i]);
}
}
printf("%lld\n",ans );
}
return 0;
}