http://acm.hdu.edu.cn/showproblem.php?pid=5834

题意:

一棵树上每个节点有一个价值$Vi$,每个节点只能获得一次,每走一次一条边要花费$Ci$,问从各个节点出发最多能收获多少价值。

思路:

需要考虑子节点和父亲节点两个方面。既然是这样,那就需要两次dfs来解决问题了,$dp[u][0]$表示从u出发最后还是回到u的最大价值和,$dp[u][1]$表示从u出发最后不回到u的最大价值和。

第一次dfs很显然就是计算出每个节点往其子树方向的$dp[u][0]$和$dp[u][1]$值。

第二次dfs就是再去考虑每个节点加上其父节点的情况,这里就需要维护一个最大值和一个次大值了,为什么呢?因为父节点的最大值可能最后停在了v子树,那么v子树到时候再去考虑父节点的时候就不对了,所以此时要将它改成次大值,这样它的最大值最后不会停在v子树。

总而言之,这是一道很经典的树形dp,不过没写出来。。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn=1e5+; int n;
int val[maxn];
int dp[maxn][];
vector<pll> G[maxn]; void dfs1(int u, int fa) //求出每个顶点往子树方向的最大值,dp[u][0]表示最终回到u,dp[u][1]表示最终不回到u
{
dp[u][]=dp[u][]=val[u];
for(int i=;i<G[u].size();i++)
{
int v=G[u][i].first;
int w=G[u][i].second;
if(v==fa) continue;
dfs1(v,u);
if(dp[v][]-*w>) dp[u][]+=dp[v][]-*w;
}
for(int i=;i<G[u].size();i++)
{
int v=G[u][i].first;
int w=G[u][i].second;
if(v==fa) continue;
int tmp = dp[u][]-max(,dp[v][]-*w)+(dp[v][]-w);
if(dp[u][]<tmp) dp[u][]=tmp;
}
} void dfs2(int u, int fa, int cost) //处理往父亲节点的方向
{
int dir_tree=u;
if(fa!=-) if(dp[fa][]-*cost>) dp[u][]+=dp[fa][]-*cost;
int sub_large=dp[u][]=dp[u][];
for(int i=;i<G[u].size();i++)
{
int v=G[u][i].first;
int w=G[u][i].second;
int tmp=dp[u][]-max(,dp[v][]-*w)+(dp[v][]-w);
if(tmp>=dp[u][]) //计算最大权值和次大权值
{
sub_large=dp[u][];
dp[u][]=tmp;
dir_tree=v;
}
else if(tmp>=sub_large) sub_large=tmp;
}
int pre0=dp[u][],pre1=dp[u][]; //出去该父节点对其子节点的影响
for(int i=;i<G[u].size();i++)
{
int v=G[u][i].first;
int w=G[u][i].second;
if(v==fa) continue;
int tmp=dp[v][]-*w;
if(tmp>) dp[u][]-=tmp; //子节点v往父节点走时,肯定不会再算v节点的子树
if(dir_tree==v) dp[u][]=sub_large; //如果u的最大值最后停留在v子树,则改成次大值
if(tmp>) dp[u][]-=tmp; //和上面的第2句相同
dfs2(v,u,w);
dp[u][]=pre0,dp[u][]=pre1;
} } int main()
{
//freopen("in.txt","r",stdin);
int T;
int kase=;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n;i++) {G[i].clear();scanf("%d",&val[i]);}
for(int i=;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
G[u].push_back(make_pair(v,w));
G[v].push_back(make_pair(u,w));
}
printf("Case #%d:\n",++kase);
dfs1(,-);
dfs2(,-,);
for(int i=;i<=n;i++) printf("%d\n",dp[i][]);
}
return ;
}

HDU 5834 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: 13107 ...

  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: ...

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

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

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

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA8UAAAJbCAIAAABCS6G8AAAgAElEQVR4nOy9fXQcxZ0uXH/hc8i5N+

  5. HDU 5834 Magic boy Bi Luo with his excited tree

    树形dp. 先dfs一次处理子树上的最优解,记录一下回到这个点和不回到这个点的最优解. 然后从上到下可以推出所有答案.细节较多,很容易写错. #pragma comment(linker, " ...

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

    题意:一棵树有点权和边权 从每个点出发 走过一条边要花费边权同时可以获得点权 边走几次就算几次花费 点权最多算一次 问每个点能获得的最大价值 题解:好吧 这才叫树形DP入门题 dp[i][0]表示从i ...

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

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

  8. 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 ...

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

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

随机推荐

  1. Java多线程面试、笔试方向---后续补充

    1.ThreadLocal类     线程级别的局部变量,为每个使用该变量的线程提供一个独立的变量副本,每个线程修改副本时不影响其他线程对象的副本.  ThreadLocal实例通常作为静态私有字段出 ...

  2. 解决PHPStorm经常卡顿现象 调整内存限制

    https://www.jisec.com/other/451.html 为什么调整内存? 最近发现PHPstorm在打开一些大点的js, html文件时,会非常的卡顿,这个主要的原因是因为设置的内存 ...

  3. Biorhythms(中国剩余定理)

    http://shuxueshi.jie.blog.163.com/blog/static/13611628820104179856631/ 这篇博客写的很棒! #include<stdio.h ...

  4. mysql 用户授权命令

    mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_root_password' WITH GRANT OP ...

  5. NSLog打印NSInteger老是有warning

    zSpecifies that a following [...] conversion specifier applies to a size_t or the corresponding sign ...

  6. unittest数据驱动

    所谓的数据驱动就是将数据单独存放,在写方法将数据读取,然后将读取的数据放在testcase里面. 当然如果这种testcase都是一样的,只有需要的数据不一样,也可以将testcase写成一个方法,把 ...

  7. sql中 substring和charindex 的用法

    -- 第一个参数是要截取的字符串,第二个参数是从第几个字符开始截取,第三个参数是截取的长度 --例如:select SUBSTRING('12345678',1,4) 返回 1234 -- selec ...

  8. windows配置iis网站域名

    1.在iis 中添加网站,网站名和主机名设置为test.com 2.在C:\Windows\System32\drivers\etc找到host文件,添加 127.0.0.1 test.com 127 ...

  9. mustache语法

    mustache 模板,用于构造html页面内容.在实际工作中,当同一个模板中想要调用不同的函数来渲染画面,在已经自定义好了的前提下,可以在渲染页面时对传入的参数进行手动判断.  以下是学习笔记内容: ...

  10. 2018-2019-2 20165209 《网络对抗技术》Exp6:信息搜集与漏洞扫描

    2018-2019-2 20165209 <网络对抗技术>Exp6:信息搜集与漏洞扫描 1 基础问题回答和实验内容 1.1基础问题回答 (1)哪些组织负责DNS,IP的管理. Intern ...