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,节点的值只能取一次,边 ...
随机推荐
- 关于mysql建立索引 复合索引 索引类型
这两天有个非常强烈的感觉就是自己在一些特别的情况下还是hold不住,脑子easy放空或者说一下子不知道怎么去分析问题了,比方,问"hash和btree索引的差别",这非常难吗.仅仅 ...
- IEDA-maven引用本地jia包
简单说下为啥用maven引用本地jar包:当在pom文件中配置需要引用了jar的坐标,但是maven引用不了(原因未知情况下),这种情况下就需要找开发提供相关依赖的的jar文件打成一个jar包发送过来 ...
- ios20--xib2
故事板控制器: // // ViewController.m // 03-通过xib自定义商品的View #import "ViewController.h" #import &q ...
- shell脚本,根据字符串获取行号的
awk中不能解析shell变量,建议做法是通过-v传递进去: 1 typeline=`cat $typepath | awk -v str="$typetmp" '/str/{pr ...
- bzoj 1090 字符串折叠
题目大意: 折叠的定义如下: 1. 一个字符串可以看成它自身的折叠.2. X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S)=SSSS…S(X个S). 3. 如果A=A’, B=B’, ...
- Java IO 字节流与字符流 (五)
Java的IO流分为字符流(Reader,Writer)和字节流(InputStream,OutputStream),字节流顾名思义字节流就是将文件的内容读取到字节数组,然后再输出到另一个文件中.而字 ...
- jquery对所有<input type="text"的控件赋值
function resetData() { $("input[type=text]").each( function() { $(this).attr ...
- 使用IntelliJ IDEA 配置JDK(入门)
一.JDK下载 首先要下载java开发工具包JDK,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 点击 ...
- bzoj 1634: [Usaco2007 Jan]Protecting the Flowers 护花【贪心】
因为交换相邻两头牛对其他牛没有影响,所以可以通过交换相邻两头来使答案变小.按照a.t*b.f排降序,模拟着计算答案 #include<iostream> #include<cstdi ...
- (DP)51NOD 1049 最大子段和
N个整数组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续子段和的最大值.当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5 ...