HDU 5834 Magic boy Bi Luo with his excited tree (树形DP)
Posted dwtfukgv
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5834 Magic boy Bi Luo with his excited tree (树形DP)相关的知识,希望对你有一定的参考价值。
题意:给定一棵树,每个点有个权值,每条边有权值,每经过边都会消耗相应的权值,但是点的权值只能获得一次,问你从 i 点出发能获得的最大权值是多少。
析:树形DP,就是太麻烦了,两次dfs,维护一共6个值分别是,从 i 出发的最大值并且返回 i, 从 i 出发的最大值并且不返回,从 i 出发的次大值并且不返回,从 i 出发的最大值的子树结点并且不返回,从 i 向父结点出发的最大值并且不返回,从 i 向父结点出发的最大值并且返回。
第一次dfs就能求出前四个,第二个dfs维护后面两个。
答案就是 max(所有子节点返回该节点+ 父亲节点不返回该节点, 有个子节点不返回该节点+从父亲节点返回该节点);
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <algorithm> #include <vector> #include <map> #include <cctype> #include <cmath> #include <stack> #include <sstream> #define debug() puts("++++"); #define gcd(a, b) __gcd(a, b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define freopenr freopen("in.txt", "r", stdin) #define freopenw freopen("out.txt", "w", stdout) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> P; const int INF = 0x3f3f3f3f; const LL LNF = 1e16; const double inf = 0x3f3f3f3f3f3f; const double PI = acos(-1.0); const double eps = 1e-8; const int maxn = 1e5 + 10; const int mod = 1e9 + 7; const int dr[] = {-1, 0, 1, 0}; const int dc[] = {0, 1, 0, -1}; const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"}; int n, m; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; inline bool is_in(int r, int c){ return r >= 0 && r < n && c >= 0 && c < m; } int val[maxn]; struct Edge{ int to, next, c; }; Edge edge[maxn<<1]; int head[maxn], cnt; int dp[maxn][4]; int ans[maxn]; /* dp[i][0] the most val and back dp[i][1] the most val and not back dp[i][2] the second most val and not back dp[i][3] the the son of the dp[i][1] */ void add_edge(int u, int v, int val){ edge[cnt].to = v; edge[cnt].c = val; edge[cnt].next = head[u]; head[u] = cnt++; } void dfs1(int u, int fa){ dp[u][0] = dp[u][1] = val[u]; dp[u][2] = 0; for(int i = head[u]; ~i; i = edge[i].next){ int v = edge[i].to; if(v == fa) continue; dfs1(v, u); } for(int i = head[u]; ~i; i = edge[i].next){ int v = edge[i].to; if(v == fa) continue; int c = edge[i].c; dp[u][0] += max(0, dp[v][0] - 2*c); } for(int i = head[u]; ~i; i = edge[i].next){ int v = edge[i].to; if(v == fa) continue; int c = edge[i].c; int val = dp[u][0] - max(0, dp[v][0] - 2*c) + max(0, dp[v][1] - c); if(val > dp[u][1]){ dp[u][2] = dp[u][1]; dp[u][1] = val; dp[u][3] = v; } else if(val > dp[u][2]) dp[u][2] = val; } } void dfs2(int u, int fa, int fb, int fnb){ ans[u] = max(fb+dp[u][1], fnb+dp[u][0]); for(int i = head[u]; ~i; i = edge[i].next){ int v = edge[i].to; if(v == fa) continue; int c = edge[i].c; int newfb = fb + dp[u][0] - max(0, dp[v][0] - 2*c); int newfnb; if(v == dp[u][3]) newfnb = max(fb + dp[u][2] - max(0, dp[v][0]-2*c), fnb + dp[u][0] - max(0, dp[v][0]-2*c)); else newfnb = max(fb + dp[u][1] - max(0, dp[v][0]-2*c), fnb + dp[u][0] - max(0, dp[v][0]-2*c)); dfs2(v, u, max(0, newfb-2*c), max(0, newfnb-c)); } } int main(){ int T; cin >> T; for(int kase = 1; kase <= T; ++kase){ scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", val+i); memset(head, -1, sizeof head); cnt = 0; for(int i = 1; i < n; ++i){ int u, v, c; scanf("%d %d %d", &u, &v, &c); add_edge(u, v, c); add_edge(v, u, c); } dfs1(1, -1); dfs2(1, -1, 0, 0); printf("Case #%d:\n", kase); for(int i = 1; i <= n; ++i) printf("%d\n", ans[i]); } return 0; }
以上是关于HDU 5834 Magic boy Bi Luo with his excited tree (树形DP)的主要内容,如果未能解决你的问题,请参考以下文章
树形动规HDU 5834 Magic boy Bi Luo with his excited tree
HDU 5834 Magic boy Bi Luo with his excited tree (树形DP)
Magic boy Bi Luo with his excited tree (树形dp)
2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree
玲珑学院OJ 1023 - Magic boy Bi Luo with his excited math problem 树状数组暴力