HDU 3534 Tree (经典树形dp)
Posted Recoder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3534 Tree (经典树形dp)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3534
题意:
给你一棵树,问你有多少对点的距离等于树的直径。
思路:
dp[i][0]表示在i的子树中 离i最远的距离,dp[i][1]是次远距离。 cnt[i][0]则是最远的点的数量,cnt[i][1]表示次远的数量。
up[i]表示以i向上 离i最远的距离。 up_cnt[i]表示向上最远的数量。
写的有点麻烦,调试了2小时。。。
1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <ctime> 10 #include <list> 11 #include <set> 12 #include <map> 13 using namespace std; 14 typedef long long LL; 15 typedef pair <int, int> P; 16 const int N = 2e5 + 5; 17 int dp[N][2]; 18 int cnt[N][2]; 19 int up[N]; 20 int cnt_up[N]; 21 int son[N][2]; 22 vector <P> G[N]; 23 24 void dfs1(int u, int p) { 25 dp[u][0] = dp[u][1] = 0; 26 son[u][0] = son[u][1] = u; 27 cnt[u][0] = cnt[u][1] = 1; 28 int tmp = 0; 29 for(int i = 0; i < G[u].size(); ++i) { 30 P temp = G[u][i]; 31 int v = temp.first; 32 if(v == p) 33 continue; 34 dfs1(v, u); 35 if(dp[v][0] + temp.second > dp[u][0]) { 36 dp[u][1] = dp[u][0]; 37 son[u][1] = son[u][0]; 38 cnt[u][1] = cnt[u][0]; 39 dp[u][0] = dp[v][0] + temp.second; 40 son[u][0] = v; 41 cnt[u][0] = cnt[v][0]; 42 tmp = cnt[v][0]; 43 } else if(dp[v][0] + temp.second == dp[u][0]) { 44 cnt[u][0] += cnt[v][0]; 45 cnt[u][1] = cnt[u][0] - tmp; 46 dp[u][1] = dp[u][0]; 47 son[u][1] = v; 48 } else if(dp[v][0] + temp.second > dp[u][1]) { 49 dp[u][1] = dp[v][0] + temp.second; 50 cnt[u][1] = cnt[v][0]; 51 son[u][1] = v; 52 } else if(dp[v][0] + temp.second == dp[u][1]) { 53 cnt[u][1] += cnt[v][0]; 54 } 55 } 56 } 57 58 void dfs2(int u, int p) { 59 for(int i = 0; i < G[u].size(); ++i) { 60 P temp = G[u][i]; 61 int v = temp.first; 62 if(v == p) 63 continue; 64 if(dp[u][0] == temp.second + dp[v][0]) { 65 //up[v] = max(up[u], dp[u][0]) + temp.second; 66 if(dp[u][1] == 0) { 67 cnt_up[v] = cnt_up[u]; 68 up[v] = up[u] + temp.second; 69 dfs2(v, u); 70 continue; 71 } 72 if(up[u] > dp[u][1]) { 73 up[v] = up[u] + temp.second; 74 cnt_up[v] = cnt_up[u]; 75 } else if(dp[u][1] > up[u]) { 76 up[v] = dp[u][1] + temp.second; 77 if(dp[u][1] == dp[u][0]) 78 cnt_up[v] = cnt[u][0] - cnt[v][0]; 79 else 80 cnt_up[v] = cnt[u][1]; 81 } else { 82 if(dp[u][1] == dp[u][0]) 83 cnt_up[v] = cnt[u][0] - cnt[v][0]; 84 else 85 cnt_up[v] = cnt[u][1]; 86 cnt_up[v] += cnt_up[u]; 87 up[v] = dp[u][1] + temp.second; 88 } 89 } else { 90 //up[v] = max(up[u], dp[u][1]) + temp.second; 91 if(up[u] > dp[u][0]) { 92 up[v] = up[u] + temp.second; 93 cnt_up[v] = cnt_up[u]; 94 } else if(dp[u][0] > up[u]) { 95 up[v] = dp[u][0] + temp.second; 96 cnt_up[v] = cnt[u][0]; 97 } else { 98 cnt_up[v] = cnt_up[u] + cnt[u][0]; 99 up[v] = dp[u][0] + temp.second; 100 } 101 } 102 dfs2(v, u); 103 } 104 } 105 106 int main() 107 { 108 int n, u, v, c; 109 while(~scanf("%d", &n)) { 110 for(int i = 1; i <= n; ++i) { 111 G[i].clear(); 112 } 113 for(int i = 1; i < n; ++i) { 114 scanf("%d %d %d", &u, &v, &c); 115 G[u].push_back(make_pair(v, c)); 116 G[v].push_back(make_pair(u, c)); 117 } 118 dfs1(1, -1); 119 cnt_up[1] = 1; 120 dfs2(1, -1); 121 int Max = 0; 122 for(int i = 1; i <= n; ++i) { 123 //cout << dp[i][0] << " - " << up[i] << endl; 124 Max = max(Max, max(dp[i][0], up[i])); 125 } 126 LL ans = 0; 127 for(int i = 1; i <= n; ++i) { 128 if(Max == dp[i][0]) { 129 ans += (LL)cnt[i][0]; 130 } 131 if(Max == up[i]) { 132 ans += (LL)cnt_up[i]; 133 } 134 } 135 printf("%d %lld\n", Max, ans/2); 136 } 137 return 0; 138 }
以上是关于HDU 3534 Tree (经典树形dp)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 6035---Colorful Tree(树形DP)
hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)