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,节点的值只能取一次,边 ...
随机推荐
- google免费DNSserver好用不?
中国的网络实在不行,网速一直就是令人诟病. 比韩日那是差太多了,可是相比非洲还是不错.可是这根本无法满足国人的上网需求.于是大家都想破了脑袋想提高网速.这不方法来了么? 笔者在网上找了几种方法关于怎样 ...
- JS 通过选择百度地图地址获取经纬度自动填充到文本框中的方法
首先要注册百度地图API. 1.登录百度地图开放平台http://lbsyun.baidu.com 注册账号,完善信息,点击网站右上角的“API控制台”,点击,创建应用. 应用类型选择:“浏览器端”, ...
- HDU 5428 分解质因数
The F ...
- 【bzoj4604】The kth maximum number
暴力 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> ...
- web metrics dashboard 数据分析工具 看板 从可视化发现问题 避免sql重复写 调高效率
<?php$todo = array();$done = array();$h = array();$v = $all['v'];$l = count($v);#19700101 08for ( ...
- 【POJ 1364】 King
[题目链接] 点击打开链接 [算法] 差分约束系统 [代码] #include <algorithm> #include <bitset> #include <cctyp ...
- POJ1279 Art Gallery 多边形的核
POJ1279 给一个多边形 求它的核的面积 所谓多边形的核 是多边形中的一个点集 满足其中的点与多边形边上的点的连线全部在多边形中 用多边形的每一条边所在的直线去切整个坐标平面 得到的一个凸包就是核 ...
- 洛谷P2680 运输计划——树上差分
题目:https://www.luogu.org/problemnew/show/P2680 久违地1A了好高兴啊! 首先,要最大值最小,很容易想到二分: 判断当前的 mid 是否可行,需要看看有没有 ...
- 移动前端第二弹:善用meta
前言 在移动前端第一弹:viewport详解中,我们讲了viewport,那是一个关于meta的故事.这次我们会就将meta这个故事讲得更广阔.更有意思一些. 写过HTML的童鞋,应该都对这个不陌生, ...
- 10.16NOIP模拟赛
/* 我是一个大sb */ #include<iostream> #include<cstdio> #include<cstring> #include<qu ...