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\n", max(dp[i][0], dp[i][2])); 75 } 76 } 77 return 0; 78 }