题意:一棵树有点权和边权 从每个点出发 走过一条边要花费边权同时可以获得点权 边走几次就算几次花费 点权最多算一次

   问每个点能获得的最大价值

题解:好吧 这才叫树形DP入门题

   dp[i][0]表示从i节点的儿子中走又回到i的最大值 dp[i][1]表示不回到i的最大值 dp[i][2]表示不回到i的次大值

   同时需要记录不回到i最大值的方向id[x]

   很显然 第一遍dfs可以预处理每个节点往下的值 然后关键的就是每个节点从父亲这个方向的值怎么处理

   有个很显然的结论就是 不回来是肯定比回来更优的 所以重点就是在处理不回来的这个支路在哪

   如果对于x节点其父亲的id[fa] = x 那么显然x,fa不回来的最大值是同一个支路 这个时候就可以更新两种答案

   在x下面的儿子中不回来 dp[x][1] = dp[x][1] += max(0, dp[fa][0] - cost[x][fa] * 2)

   在fa中的其他儿子中不回来就用到了次大 dp[x][1] = dp[x][0] + dp[fa][2] - cost[x][fa]

   如果id[fa] != x  dp[x][1] = dp[x][0] + dp[fa][1] - cost[x][fa]

   最后再更新dp[x][0] = dp[x][0] + max(0, dp[fa][0] - cost[x][fa] * 2) 同时转移的时候次大 以及最大的方向都要更新

   不过这里的dp值显然都是要减去重复计算的部分 具体代码见

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std; int n, cnt;
int q[];
int dp[][];
int du[];
int head[];
int id[]; struct node
{
int no, to, nex, val;
}E[]; void dfs1(int x, int fa)
{
dp[x][] = q[x];
dp[x][] = q[x];
dp[x][] = q[x];
int c = head[x];
for(int i = c; i; i = E[i].nex)
{
int v = E[i].to;
if(v == fa) continue; dfs1(v, x);
if(E[i].val * < dp[v][]) dp[x][] += dp[v][] - E[i].val * ;
} for(int i = c; i; i = E[i].nex)
{
int v = E[i].to;
if(v == fa) continue; int tmp = dp[x][];
if(E[i].val * < dp[v][]) tmp += E[i].val * - dp[v][]; if(tmp + dp[v][] - E[i].val >= dp[x][])
{
dp[x][] = dp[x][];
dp[x][] = tmp + dp[v][] - E[i].val;
id[x] = v;
}
else if(tmp + dp[v][] - E[i].val > dp[x][]) dp[x][] = tmp + dp[v][] - E[i].val; dp[x][] = max(dp[x][], dp[x][]);
}
} void dfs2(int x, int fa)
{
int c = head[x];
for(int i = c; i; i = E[i].nex)
{
int v = E[i].to;
if(v != fa) continue; int tmp0 = dp[fa][];
int tmp1 = dp[fa][];
int tmp2 = dp[fa][];
if(E[i].val * < dp[x][])
{
tmp0 += E[i].val * - dp[x][];
if(id[fa] != x) tmp1 += E[i].val * - dp[x][];
else tmp2 += E[i].val * - dp[x][];
}
tmp0 = max(tmp0, ); tmp1 = max(tmp1, ); tmp2 = max(tmp2, ); //dp[x][0] = max(dp[x][0], dp[x][0] - E[i].val * 2 + tmp0); 因为下面的转移用到了dp[x][0] 写在这里就不对
if(tmp0 - E[i].val * > )
{
dp[x][] += tmp0 - E[i].val * ;
dp[x][] += tmp0 - E[i].val * ;
} if(id[fa] == x)
{
if(dp[x][] - E[i].val + tmp2 >= dp[x][])
{
dp[x][] = dp[x][];
dp[x][] = dp[x][] - E[i].val + tmp2;
id[x] = fa;
}
else if(dp[x][] - E[i].val + tmp2 > dp[x][]) dp[x][] = dp[x][] - E[i].val + tmp2;
}
else
{
if(dp[x][] - E[i].val + tmp1 >= dp[x][])
{
dp[x][] = dp[x][];
dp[x][] = dp[x][] - E[i].val + tmp1;
id[x] = fa;
}
else if(dp[x][] - E[i].val + tmp1 > dp[x][]) dp[x][] = dp[x][] - E[i].val + tmp1;
}
dp[x][] = max(dp[x][], dp[x][] - E[i].val * + tmp0);
} for(int i = c; i; i = E[i].nex)
{
int v = E[i].to;
if(v == fa) continue;
dfs2(v, x);
}
} int main()
{
int T;
scanf("%d", &T);
int t = ; while(T--)
{
t++;
cnt = ;
scanf("%d", &n);
memset(id, , sizeof(id));
memset(head, , sizeof(head));
memset(dp, , sizeof(dp));
memset(du, , sizeof(du));
for(int i = ; i <= n; i++) scanf("%d", &q[i]); for(int i = ; i < n; i++)
{
int u, v, w; scanf("%d%d%d", &u, &v, &w); du[u]++; du[v]++;
E[++cnt].no = u, E[cnt].to = v, E[cnt].nex = head[u], head[u] = cnt, E[cnt].val = w;
E[++cnt].no = v, E[cnt].to = u, E[cnt].nex = head[v], head[v] = cnt, E[cnt].val = w;
} int rt;
for(int i = ; i <= n; i++)
if(du[i] == )
{
rt = i;
break;
} dfs1(rt, -);
dfs2(rt, -);
printf("Case #%d:\n", t);
for(int i = ; i <= n; i++) printf("%d\n", max(dp[i][], dp[i][]));
}
return ;
}

  

HDU5834 Magic boy Bi Luo with his excited tree (树形DP)的更多相关文章

  1. hdu-5834 Magic boy Bi Luo with his excited tree(树形dp)

    题目链接: Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: ...

  2. hdu 5834 Magic boy Bi Luo with his excited tree 树形dp+转移

    Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 13107 ...

  3. 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree

    // 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以 ...

  4. HDU5834 Magic boy Bi Luo with his excited tree(树形DP)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5834 Description Bi Luo is a magic boy, he also ...

  5. hdu5834 Magic boy Bi Luo with his excited tree 【树形dp】

    题目链接 hdu5834 题解 思路很粗犷,实现很难受 设\(f[i][0|1]\)表示向子树走回来或不回来的最大收益 设\(g[i][0|1]\)表示向父亲走走回来或不回来的最大收益 再设\(h[i ...

  6. HDU5834Magic boy Bi Luo with his excited tree 树形dp

    分析:典型的两遍dfs树形dp,先统计到子树的,再统计从祖先来的,dp[i][0]代表从从子树回来的最大值,dp[i][1]代表不回来,id[i]记录从i开始到哪不回来 吐槽:赛场上想到了状态,但是不 ...

  7. 2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree

    Magic boy Bi Luo with his excited tree Problem Description Bi Luo is a magic boy, he also has a migi ...

  8. 动态规划(树形DP):HDU 5834 Magic boy Bi Luo with his excited tree

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA8UAAAJbCAIAAABCS6G8AAAgAElEQVR4nOy9fXQcxZ0uXH/hc8i5N+

  9. 【树形动规】HDU 5834 Magic boy Bi Luo with his excited tree

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5834 题目大意: 一棵N个点的有根树,每个节点有价值ci,每条树边有费用di,节点的值只能取一次,边 ...

随机推荐

  1. web 开发之js---js 实现网页中播放wav的一种方法(flash播放器)

    http://blog.csdn.net/whumr1/article/details/6948160

  2. 剑指Offer面试题29(java版):数组中出现次数超过一半的数字

    题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 比如输入一个长度为9的数组{1,2,3,2.2,2.5,4,2}.因为数字2在数组中出现5次,超过数组长度的一半,因此输出2. 解 ...

  3. 使用-Wl直接向ld传递参数

    gcc -Wl, key1, value1, key2, value2, key3, value3 包括-Wl在内全部都是以逗号分隔. 上面等价于: ld key1=value1 key2=value ...

  4. canvas绘图数学知识总结

    题外话: 最近看了一本书叫 <HTML5 Canvas核心技术 图形.动画与游戏开发>已经算是看了85%,基本接近尾声,所以近期会多总结一些关于canvas的东西, 这本书讲的还算可以,最 ...

  5. 修改Android系统的触摸提示音【学习笔记】

    平台信息:内核:Linux version 3.10.0系统:android/android6.0平台:rk3288 作者:庄泽彬(欢迎转载,请注明作者) 邮箱:2760715357@qq.com 本 ...

  6. jquery uploadify在谷歌浏和火狐下无法上传的解决方案(.Net版)

    在项目紧张的进行过程中,jquery uploadify上传不兼容的问题一直没有试着去解决,只幻想着用ie的人越来越多,怎么奈何firefox4刚推出,就有4000万的下载.......仰天长叹,记生 ...

  7. 第十一周 Leetcode 576. Out of Boundary Paths (HARD) 计数dp

    Leetcode 576 给定一个二维平面, 一个球在初始位置(i,j)每次可以转移到上下左右的一格. 问在N次转移内,有多少种路径可以转移出边境. dp[i][j][k]为 在点(i,j) 已经走了 ...

  8. bzoj1047

    二维单调队列 rmq很明显会超时,如果这个序列是一维的,很明显就是个单调队列,现在就是把一维的单调队列转换为二维单调队列. 先求出每一列的窗口极值,然后对于每一行做单调队列,值就是之前求出每个位置结尾 ...

  9. codeforces round #428 div2

    A:暴力模拟,能加就加,如果累计到了8就加上,每次累积 #include<bits/stdc++.h> using namespace std; int main() { ; scanf( ...

  10. vue项目开发中踩过的坑

    一.路由 这两天移动端的同事在研究vue,跟我说看着我的项目做的,子路由访问的时候是空白的,我第一反应是,不会模块没加载进来吧,还是....此处省略一千字... 废话不多说上代码 路由代码 { pat ...