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 u and 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
5 1 2 5 3 4 7 2 3 3 2 5 2
Sample Output 1
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 is 38.
Sample Input 2
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
132
思路:按边考虑,计算每条边最多能贡献几次,发现只要围着树的重心对称跑,每条边都能充分利用,边i的贡献为它的较小子树节点数*2*边权值,但有一条边例外,假如树的重心只有一个,该重心相连的一条边贡献减一,自然是减最小那条边。当有两个重心,减去两重心相连的边即可。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+30;
int n, id=0, cnt=0, Next[maxn], in[maxn], out[maxn], son[maxn]={0}, zhong[maxn];
int msize = 0x3f3f3f3f, mid;
LL ans = 0;
struct node{int e, w, next;}edge[maxn<<1];
void add_edge(int u, int v, int w)
{
edge[cnt] = {v, w, Next[u]};
Next[u] = cnt++;
edge[cnt] = {u, w, Next[v]};
Next[v] = cnt++;
}
void dfs(int cur, int pre, int w)
{
in[cur] = ++id;
int imax = 0;
for(int i=Next[cur]; i!=-1; i=edge[i].next)
{
int v = edge[i].e;
if(v == pre) continue;
dfs(v, cur, edge[i].w);
son[cur] += son[v] + 1;
imax = max(imax, son[v]+1);
}
out[cur] = id;
int imin = min(out[cur]-in[cur]+1, n-out[cur]+in[cur]-1);
ans = ans + (LL)imin*w*2;
imax = max(imax, n-1-son[cur]);
zhong[cur] = imax;
if(imax < msize)
{
msize = imax;
mid = cur;
}
}
int main()
{
memset(Next, -1, sizeof(Next));
int a, b, c;
scanf("%d",&n);
for(int i=1; i<n; ++i)
{
scanf("%d%d%d",&a,&b,&c);
add_edge(a, b, c);
}
dfs(1, 0, 0);
int com = 0x3f3f3f3f;
for(int i=Next[mid]; i!=-1; i=edge[i].next)
{
int v = edge[i].e;
com = min(com, edge[i].w);
if(zhong[v] == zhong[mid])
{
ans -= edge[i].w;
return 0*printf("%lld\n",ans);
}
}
printf("%lld\n",ans-com);
return 0;
}