题目链接:http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1267
Highway
In ICPCCamp there were n towns conveniently numbered with 1,2,…,n connected with (n−1) roads. The i -th road connecting towns ai and bi has length ci . It is guaranteed that any two cities reach each other using only roads.
Bobo would like to build (n−1) highways so that any two towns reach each using only highways. Building a highway between towns x and y costs him δ(x,y) cents, where δ(x,y) is the length of the shortest path between towns x and y using roads.
As Bobo is rich, he would like to find the most expensive way to build the (n−1) highways.
Input
The input contains zero or more test cases and is terminated by end-of-file. For each test case:
The first line contains an integer n . The i -th of the following (n−1) lines contains three integers ai , bi and ci .
- 1≤n≤105
- 1≤ai,bi≤n
- 1≤ci≤108
- The number of test cases does not exceed 10 .
Output
For each test case, output an integer which denotes the result.
Sample Input
5 1 2 2 1 3 1 2 4 2 3 5 1 5 1 2 2 1 4 1 3 4 1 4 5 2
Sample Output
19 15
题目大意:给你一颗已知的树,求出新建的一颗权值最大的树的权值
解题思路:树形dp,求出每个点到树其他点的最长距离再减去树中的最长路径。
将每个点的最长路径添加到新建的树中,除了树中最长的那条路径会重复一次(构成一个环),不会形成其他环,而所有的点都添加到了新建的树中,于是构成了一颗权值最大的树。
dp[u][0]:u到子树节点的最长距离,dp[u][1]:u到子树节点外其他节点的最长距离
dp[u][0]很容易在dfs中计算出来。
dp[v][1]:若v不是u子树最长路径经过的点,dp[v][1] = max( dp[u][1]+Luv , dp[u][0]+Luv )
若v是u子树最长路径所经过的点,dp[v][1] = max( dp[u][1]+Luv , dp[u][0]+Se[u])
Se[u]带表u的子树中第二长的路径长度。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#include <set>
#include <string>
#include <stack>
#include <algorithm>
#include <map>
using namespace std;
typedef __int64 ll;
const int N = 100100;
const int M = 20;
const int INF = 0x3fffffff;
struct Edge
{
int node,len;
Edge*next;
}m_edge[N*2];
int Ecnt;
Edge*head[N];
int vis[N],flag[N];
ll dp[N][2],second[N];
//dp[u][0]:u到子树节点的最长距离,dp[u][1]:u到子树节点外其他节点的最长距离
//second[u]:子树节点到u的第二长路径,flag[v]:节点v的上层节点的最长路径是否经过v
void init()
{
Ecnt = 0;
fill( head , head+N , (Edge*)0 );
fill( flag , flag+N , 0 );
fill( second , second+N , 0 );
}
void mkEdge( int a , int b , int c )
{
m_edge[Ecnt].node = a;
m_edge[Ecnt].len = c;
m_edge[Ecnt].next = head[b];
head[b] = m_edge+Ecnt++;
m_edge[Ecnt].node = b;
m_edge[Ecnt].len = c;
m_edge[Ecnt].next = head[a];
head[a] = m_edge+Ecnt++;
}
ll dfs1( int u )
{
vis[u] = true; dp[u][0] = 0;
for( Edge*p = head[u] ; p ; p = p->next ){
int v = p->node;
if( !vis[v] ){
ll w = dfs1( v );
dp[u][0] = max( dp[u][0] , w+p->len );
}
}
return dp[u][0];
}
void dfs2( int u )
{
vis[u] = true;
int fg = 0;
for( Edge*p = head[u] ; p ; p = p ->next ){
int v = p->node;
if( !vis[v] ){
if( !fg && dp[u][0] == dp[v][0]+p->len ) { flag[v] = 1;fg = 1; }
else second[u] = max( second[u] , dp[v][0]+p->len );
dfs2( v );
}
}
}
void dfs3( int u )
{
vis[u] = true;
for( Edge*p = head[u] ; p ; p = p->next ){
int v = p->node;
if( !vis[v] ){
if( !flag[v] ) dp[v][1] = max( dp[u][1]+p->len , dp[u][0]+p->len );
else dp[v][1] = max( dp[u][1]+p->len , second[u]+p->len );
dfs3( v );
}
}
}
int main()
{
int n,a,b,c;
while( ~scanf("%d",&n) ){
init();
for( int i = 0 ; i < n-1 ; ++i ){
scanf("%d%d%d",&a,&b,&c);
mkEdge( a , b , c );
}
memset( vis , 0 , sizeof(vis) );
dfs1( 1 );
memset( vis , 0 , sizeof(vis) );
dfs2( 1 );
memset( vis , 0 , sizeof(vis) );
dfs3( 1 );
ll rec = 0,ans = 0;
for( int i = 1 ; i <= n ; ++i ){
ll t = max( dp[i][0] , dp[i][1] );
ans += t;
rec = max( rec , t );
}
ans -= rec;
printf("%I64d\n",ans);
}
return 0;
}