选取任意一节点作为根节点,我选的是1,然后先用一次DFS求出每个节点向下的最大权值和,然后第二次DFS的时候先更新向上的最大权值和,然后求出向上向下中最大的权值和即为该点的所求值。 其中的更新的正确性可以用数学归纳法证明。(初始正确, 每步之后正确)
其实自己画图就能明白,可能说的不清楚,最好自己画图看看。
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef struct{
int to;
int next;
int length;
int sum;
}Edge;
Edge edge[20002];
int N;
int head[10001];
int tot;
bool visit1[10001], visit2[10001];
__int64 m[10001];
__int64 dp[10001];
inline __int64 max( __int64 a, __int64 b ){
return ( a > b ? a : b );
}
void add_edge( int a, int b, int length ){
edge[tot].to = b;
edge[tot].next = head[a];
edge[tot].length = length;
head[a] = tot++;
edge[tot].to = a;
edge[tot].next = head[b];
edge[tot].length = length;
head[b] = tot++;
}
void DFS1( int n, int pre ){
visit1[n] = true;
int t = head[n];
if( edge[t].to == pre ){
m[n] = 0;
return;
}
for( int i = head[n]; i != -1; i = edge[i].next ){
int t = edge[i].to;
if( visit1[t] ){
continue;
}
DFS1( t, n );
m[n] = max( m[n], m[t] + edge[i].length );
edge[i].sum = m[t] + edge[i].length;
}
}
void DFS2( int n, int pre ){
//
int maxi = 0;
for( int i = head[pre]; i != -1; i = edge[i].next ){
if( edge[i].to != n ){
maxi = max( maxi, edge[i].sum );
}
}
for( int i = head[n]; i != -1; i = edge[i].next ){//注意这里一定是要更新从n到pre的边 而不是从pre到你的边
if( edge[i].to == pre ){
edge[i].sum = maxi + edge[i].length;
break;
}
}
for( int i = head[n]; i != -1; i = edge[i].next ){
dp[n] = max( dp[n], edge[i].sum );
}
visit2[n] = true;
//
for( int i = head[n]; i != -1; i = edge[i].next ){
int t = edge[i].to;
if( visit2[t] ){
continue;
}
DFS2( t, n );
}
}
int main(){
while( scanf( "%d", &N ) != EOF ){
memset( visit1, false, sizeof( visit1 ) );
memset( visit2, false, sizeof( visit2 ) );
memset( head, -1, sizeof( head ) );
memset( m, 0, sizeof( m ) );
memset( dp, 0, sizeof( dp ) );
tot = 0;
for( int i = 2; i <= N; i++ ){
int temp1, temp2;
cin >> temp1 >> temp2;
add_edge( i, temp1, temp2 );
}
DFS1( 1, -1 );
dp[1] = m[1];
for( int i = head[1]; i != -1; i = edge[i].next ){
DFS2( edge[i].to, 1 );
}
for( int i = 1; i <= N; i++ ){
printf( "%I64d\n", dp[i] );
}
}
return 0;
}