HDU 2196 Computer (树dp)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=2196

给你n个点,n-1条边,然后给你每条边的权值。输出每个点能对应其他点的最远距离是多少。

树形dp,2次dfs。

第一次 dfs1自低向上回溯更新:dp[i][0]表示从底部到i点的最远距离,dp[i][1]则表示次远距离 (dp[i][2]时用到)

    dp[i][0] = max(dp[i][0], dp[i的子节点][0] + edge);

第二次 dfs2自顶向下顺着更新:dp[i][2]表示从前部到i点的最远距离,顺着下来。

    1)要是dp[i父节点][0]由i点转移 :dp[i][2] = max(dp[i父节点][2] , dp[i父节点][1]) + edge; 

      当然只有一条边的话就:dp[i][2] = dp[i父节点][2];

    2)否则 :dp[i][2] = max(dp[i父节点][2] , dp[i父节点][0]) + edge;

 1 //HDU 2196
 2 //#pragma comment(linker, "/STACK:102400000, 102400000")
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <cstring>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <ctime>
11 #include <list>
12 #include <set>
13 #include <map>
14 using namespace std;
15 typedef long long LL;
16 typedef pair <int, int> P;
17 const int N = 1e5 + 5;
18 struct Edge {
19     int next, to, cost;
20 }edge[N << 1];
21 int dp[N][3], head[N], cnt;
22 
23 inline void add(int u, int v, int c) {
24     edge[cnt].to = v;
25     edge[cnt].next = head[u];
26     edge[cnt].cost = c;
27     head[u] = cnt++;
28 }
29 
30 void dfs1(int u, int p) {
31     for(int i = head[u]; ~i; i = edge[i].next) {
32         int v = edge[i].to;
33         if(v == p)
34             continue;
35         dfs1(v, u);
36         if(edge[i].cost + dp[v][0] >= dp[u][0]) {
37             dp[u][1] = dp[u][0];
38             dp[u][0] = dp[v][0] + edge[i].cost;
39         } else {
40             dp[u][1] = max(dp[v][0] + edge[i].cost, dp[u][1]);
41         }
42     }
43 }
44 
45 void dfs2(int u, int p, int val) {
46     for(int i = head[u]; ~i; i = edge[i].next) {
47         int v = edge[i].to;
48         if(v == p)
49             continue;
50         if(dp[u][0] == dp[v][0] + edge[i].cost) {
51             dp[v][2] = max(dp[u][1], val) + edge[i].cost;
52         } else {
53             dp[v][2] = max(dp[u][0], val) + edge[i].cost;
54         }
55         dfs2(v, u, dp[v][2]);
56     }
57 }
58 
59 int main()
60 {
61     int n, u, v;
62     while(~scanf("%d", &n)) {
63         memset(head, -1, sizeof(head));
64         cnt = 0;
65         for(int i = 2; i <= n; ++i) {
66             scanf("%d %d", &u, &v);
67             add(i, u, v);
68             add(u, i, v);
69         }
70         memset(dp, 0, sizeof(dp));
71         dfs1(1, -1);
72         dfs2(1, -1, 0);
73         for(int i = 1; i <= n; ++i) {
74             printf("%d
", max(dp[i][0], dp[i][2]));
75         }
76     }
77     return 0;
78 }
原文地址:https://www.cnblogs.com/Recoder/p/5821336.html