您的位置:首页 > 其它

AtCoder Grand Contest 018--D题

2017-07-27 17:07 399 查看


D - Tree and Hamilton Path

Time limit : 2sec / Memory limit : 256MB

Score : 1100 points

Problem Statement

There is a tree with N vertices,
numbered 1 through N.
The i-th edge in this tree connects Vertices Ai and Bi and
has a length of Ci.
Joisino created a complete graph with N vertices.
The length of the edge connecting Vertices u and v in
this graph, is equal to the shortest distance between Vertices uand v in
the tree above.
Joisino would like to know the length of the longest Hamiltonian path (see Notes) in this complete graph. Find the length of that path.

Notes

A Hamiltonian path in a graph is a path in the graph that visits each vertex exactly once.

Constraints

2≤N≤105
1≤Ai<Bi≤N
The given graph is a tree.
1≤Ci≤108
All input values are integers.

Input

Input is given from Standard Input in the following format:
N
A1 B1 C1
A2 B2 C2
:
AN−1 BN−1 CN−1


Output

Print the length of the longest Hamiltonian path in the complete graph created by Joisino.

Sample Input 1

Copy
5
1 2 5
3 4 7
2 3 3
2 5 2


Sample Output 1

Copy
38

The length of the Hamiltonian path 5 → 3 → 1 → 4 → 2 is 5+8+15+10=38.
Since there is no Hamiltonian path with length 39 or greater in the graph, the answer is38.

Sample Input 2

Copy
8
2 8 8
1 5 1
4 8 2
2 5 4
3 8 6
6 8 9
2 7 12


Sample Output 2

Copy
132


题解:

case1:存在一条边,移除这条边后,树分成两个顶点数目相同的子树。如1-2-3-4-5-6 树形图,拆掉3-4这条边,交叉的访问这两个集合中的点,最优的顶点访问序列就是:3->6->2->5->1->4,一共经过17条边;

case2:存在一个顶点G,移除这个顶点以及与该点相连的边,图分成K个部分,每个部分的顶点数目Ti<=N/2,(i=1,...K)。那么,我们把G点作为访问的第一个点,再从这K个连通部分中,找到一个点v作为最后一个访问的顶点,要求该顶点v需与G直接相连。这样,就可以构造一个序列,使得属于同一个连通集里的两个顶点不会相邻。





#include <iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#include<map>
#include<cmath>
using namespace std;
#define LL long long
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,a,n) for(int i=n-1;i>=a;--i)
#define mem(a,t) memset(a,t,sizeof(a))
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define all(v) v.begin(),v.end()
#define sz(v) ((int)sizeof(v))
const int inf=1e9;
const int N=1e5+5;
int n,splen=0,spv;
LL ans=0;
vector<pair<int,int> >g
;
int c
;

void dfs(int u,int pre,int len){
c[u]=1;
int v,w,child=0;
for(int i=0;i<g[u].size();++i){
v=g[u][i].fi;
if(v==pre) continue;
dfs(v,u,g[u][i].se);
c[u]+=c[v];
child=max(child,c[v]);
}
child=max(child,n-c[u]);
if(c[u]*2==n){    //case1
splen=len;
}
if(child<=n/2){         //case2
spv=u;               //特殊点G,
}
ans+=2ll*len*min(c[u],n-c[u]);
}

int main(){
ios_base::sync_with_stdio(false);
cin>>n;
int u,v,w;
rep(i,0,n-1){
cin>>u>>v>>w;
g[u].pb(mp(v,w));
g[v].pb(mp(u,w));
}
dfs(1,0,0);
if(splen){            //case1
cout<<ans-splen<<endl;
}
else{              //case2
int mi=1e9;
for(int i=0;i<g[spv].size();++i){    //找到和特殊点相邻的最小边e
mi=min(mi,g[spv][i].se);
}
cout<<ans-mi<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: