求树上的每个节点能到达的最远距离。
先预处理出每个节点从叶子上来的最大距离和次大距离,并且记录最大距离是从哪个儿子上来的。
对于每个节点,它能到的最大距离,要不就是走到自己的某个叶子,要不就是走到某个祖先节点然后转弯进入这个祖先的另一个儿子。向下DP,传递不经过这棵子树到该顶点的最大距离。
1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm> 4 #define MAXN 10001 5 #define INF 0x3f3f3f3f 6 using namespace std; 7 8 struct egde{ 9 int v, w, n; 10 }e[MAXN*2]; 11 int n, tu, tv, ans; 12 int first[MAXN], es; 13 void addedge(int u, int v, int w){ 14 e[es].v = v, e[es].w = w; 15 e[es].n = first[u], first[u] = es++; 16 } 17 int mson[MAXN][2], mdis[MAXN][2], d[MAXN]; 18 void dp1(int u, int f){ 19 mdis[u][0] = mdis[u][1] = 0, mson[u][0] = mson[u][1] = -1; 20 for (int i = first[u]; i != -1; i = e[i].n) { 21 int v = e[i].v; 22 if (v == f) continue; 23 dp1(v, u); 24 if (mdis[v][0] + e[i].w > mdis[u][1]) mdis[u][1] = mdis[v][0] + e[i].w, mson[u][1] = v; 25 if (mdis[u][1] > mdis[u][0]) swap(mdis[u][0], mdis[u][1]), swap(mson[u][0], mson[u][1]); 26 } 27 } 28 void dp2(int u, int f, int w){ 29 d[u] = max(mdis[u][0], w); 30 for (int i = first[u] ; i != -1; i = e[i].n) { 31 int v = e[i].v; 32 if (v == f) continue; 33 int tmp = (mson[u][0]==v ? mdis[u][1]+e[i].w : mdis[u][0]+e[i].w); 34 dp2(v, u, max(w+e[i].w, tmp)); 35 } 36 } 37 int main(){ 38 scanf("%d", &n); 39 memset(first, -1, sizeof first); es = 0; 40 for (int i = 2; i <= n; i++) { 41 scanf("%d%d", &tu, &tv); 42 addedge(i, tu, tv); 43 addedge(tu, i, tv); 44 } 45 dp1(1, -1); 46 dp2(1, -1, 0); 47 for (int i = 1; i <= n; i++) printf("%d\n", d[i]); 48 return 0; 49 }