HDU5834 Magic boy Bi Luo with his excited tree (树形DP)
题意:一棵树有点权和边权 从每个点出发 走过一条边要花费边权同时可以获得点权 边走几次就算几次花费 点权最多算一次
问每个点能获得的最大价值
题解:好吧 这才叫树形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)的更多相关文章
- 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: ...
- 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 ...
- 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree
// 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以 ...
- 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 ...
- hdu5834 Magic boy Bi Luo with his excited tree 【树形dp】
题目链接 hdu5834 题解 思路很粗犷,实现很难受 设\(f[i][0|1]\)表示向子树走回来或不回来的最大收益 设\(g[i][0|1]\)表示向父亲走走回来或不回来的最大收益 再设\(h[i ...
- HDU5834Magic boy Bi Luo with his excited tree 树形dp
分析:典型的两遍dfs树形dp,先统计到子树的,再统计从祖先来的,dp[i][0]代表从从子树回来的最大值,dp[i][1]代表不回来,id[i]记录从i开始到哪不回来 吐槽:赛场上想到了状态,但是不 ...
- 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 ...
- 动态规划(树形DP):HDU 5834 Magic boy Bi Luo with his excited tree
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA8UAAAJbCAIAAABCS6G8AAAgAElEQVR4nOy9fXQcxZ0uXH/hc8i5N+
- 【树形动规】HDU 5834 Magic boy Bi Luo with his excited tree
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5834 题目大意: 一棵N个点的有根树,每个节点有价值ci,每条树边有费用di,节点的值只能取一次,边 ...
随机推荐
- Android自己定义组件系列【5】——进阶实践(2)
上一篇<Android自己定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这 ...
- cocos2dx 纹理优化
description: 为什么要谈纹理的问题,游戏的画面无时无刻不充斥着图像,通俗意义上一款精致的游戏都有着非常精美的画面.这样往往能给玩家带来更好的游戏体验,这一点也是对于游戏制作者来说所尽力追求 ...
- 嵌入式开发之8127---DM8127如何利用EDMA搬移数据
--------------qq:1327706646 ---------------------author:midu -------------------------------datetime ...
- asp.net mvc 的 视图(view )的模块化开发
目前所在项目有一个视图,几个模块都涉及到,对应不同的开发人员,虽然有SVN在管理,但代码冲突时有发生.并且大家的代码挤于其中,逻辑比较容易混乱. 将不同部件独立出去,实有必要. 分离方式,我知道的有 ...
- 【Learning】多项式的一些东西
FFT 坑 NTT 将\(FFT\)中的单位复数根改成原根即可. 卡常版NTT模版 struct Mul { int Len; int wn[N], Lim; int rev[N]; inline v ...
- 使用frp工具实现内网的穿透以及配置多个ssh和web服务
frp简介 FRP 项目地址 https://github.com/fatedier/frp/blob/master/README_zh.md frp 是一个可用于内网穿透的高性能的反向代理应用,支持 ...
- Linux学习笔记之Linux用户与用户组、文件操作命令、文件权限剖析
1.用户与用户组 Linux是一个多用户操作系统,通过用户与用户组的概念,可以实现保证安全性和隐私性.任何一个文件都具有User.Group.Others三个权限. 文件拥有者(Linux下所有的东西 ...
- python自动化测试学习笔记-8多线程
线程模块 python的多线程只能利用cpu的一个核心,一个核心同时只能运行一个任务那么为什么你使用多线程的时候,它的确是比单线程快答:如果是一个计算为主的程序(专业一点称为CPU密集型程序),这一点 ...
- ROS-URDF仿真
前言:URDF (标准化机器人描述格式),是一种用于描述机器人及其部分结构.关节.自由度等的XML格式文件. 一.首先做一个带有四个轮子的机器人底座. 1.1 新建urdf文件 在chapter4_t ...
- 260 Single Number III 数组中除了两个数外,其他的数都出现了两次,找出这两个只出现一次的数
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其他所有元素均出现两次. 找出只出现一次的那两个元素.示例:给定 nums = [1, 2, 1, 3, 2, 5], 返回 [3, 5].注 ...