题目

Source

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

Description

Bi Luo is a magic boy, he also has a migic tree, the tree has N nodes , in each node , there is a treasure, it's value is V[i], and for each edge, there is a cost C[i], which means every time you pass the edge i , you need to pay C[i].

You may attention that every V[i] can be taken only once, but for some C[i] , you may cost severial times.

Now, Bi Luo define ans[i] as the most value can Bi Luo gets if Bi Luo starts at node i.

Bi Luo is also an excited boy, now he wants to know every ans[i], can you help him?

Input

First line is a positive integer T(T≤104) , represents there are T test cases.

Four each test:

The first line contain an integer N(N≤105).

The next line contains N integers V[i], which means the treasure’s value of node i(1≤V[i]≤104).

For the next N−1 lines, each contains three integers u,v,c , which means node u and node v are connected by an edge, it's cost is c(1≤c≤104).

You can assume that the sum of N will not exceed 106.

Output

For the i-th test case , first output Case #i: in a single line , then output N lines , for the i-th line , output ans[i] in a single line.

Sample Input

1
5
4 1 7 7 7
1 2 6
1 3 1
2 4 8
3 5 2

Sample Output

Case #1:
15
10
14
9
15

分析

题目大概说给一棵树,点和边都有权值,经过一点可以加上该点的权值但最多只加一次,经过边会减去该边权值,问从各个点分别出发最多能获得多少权值。

这题是很裸的一种树形DP,做过类似HDU2196就知道怎么做了。两个DFS分别在O(n)处理出两种信息,各个结点往其为根的子树走的信息各个结点往父亲走的信息,各个结点就能在O(1)合并这两个信息分别得出各个结点的最终信息。。

对于这题需要的状态是:

  • dp_down[0/1][u]:u结点往其为根的子树走,并且不走回来/走回来,能得到的最大权值
  • dp_up[0/1][u]:u结点往其父亲向上走,并且不走回来/走回来,能得到的最大权值

转移的话,想想就知道了。。dp_up[1][u]可以通过计算各个孩子信息的最大值和次大值求得,其他的比较简单,不过麻烦。。细节要注意,逻辑好考虑清楚。。比赛时我就没考虑好几个逻辑WA了,然后死活找不到错,还好队友A了。。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 111111 struct Edge{
int v,w,next;
}edge[MAXN<<1];
int NE,head[MAXN];
void addEdge(int u,int v,int w){
edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u];
head[u]=NE++;
} int val[MAXN];
int d_down[2][MAXN],d_up[2][MAXN]; void dfs1(int u,int fa){
d_down[0][u]=d_down[1][u]=val[u];
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
dfs1(v,u);
if(d_down[0][v]-2*edge[i].w>0) d_down[0][u]+=d_down[0][v]-2*edge[i].w;
}
int mx=0;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
if(d_down[0][v]-2*edge[i].w>0){
mx=max(mx,(d_down[1][v]-edge[i].w)-(d_down[0][v]-2*edge[i].w));
}else{
mx=max(mx,d_down[1][v]-edge[i].w);
}
}
d_down[1][u]=d_down[0][u]+mx;
}
void dfs2(int u,int fa){ int mx1=0,mx2=0,tmp;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
if(d_down[0][v]-2*edge[i].w>0) tmp=(d_down[1][v]-edge[i].w)-(d_down[0][v]-2*edge[i].w);
else tmp=d_down[1][v]-edge[i].w;
if(mx1<tmp){
mx2=mx1;
mx1=tmp;
}else if(mx2<tmp){
mx2=tmp;
}
} for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue; int tmp2;
if(d_down[0][v]-2*edge[i].w>0){
tmp2=d_down[0][u]-(d_down[0][v]-2*edge[i].w);
}else{
tmp2=d_down[0][u];
}
int mx=max(d_up[0][u]-2*edge[i].w,tmp2-2*edge[i].w);
mx=max(mx,d_up[0][u]+tmp2-2*edge[i].w-val[u]);
d_up[0][v]=val[v]+max(0,mx); if(d_down[0][v]-2*edge[i].w>0){
if(mx1==(d_down[1][v]-edge[i].w)-(d_down[0][v]-2*edge[i].w)) tmp=d_down[1][u]-(d_down[1][v]-edge[i].w)+mx2;
else tmp=d_down[1][u]-(d_down[0][v]-2*edge[i].w);
}else if(d_down[1][v]-edge[i].w>0){
if(mx1==d_down[1][v]-edge[i].w) tmp=d_down[1][u]-(d_down[1][v]-edge[i].w)+mx2;
else tmp=d_down[1][u];
}else tmp=d_down[1][u];
mx=max(d_up[1][u]-edge[i].w,tmp-edge[i].w);
mx=max(mx,max(d_up[0][u]+tmp-edge[i].w-val[u],d_up[1][u]+tmp2-edge[i].w-val[u]));
d_up[1][v]=val[v]+max(0,mx); dfs2(v,u);
}
} int main(){
int t;
scanf("%d",&t);
for(int cse=1; cse<=t; ++cse){
NE=0;
memset(head,-1,sizeof(head));
int n;
scanf("%d",&n);
for(int i=1; i<=n; ++i){
scanf("%d",val+i);
}
int a,b,c;
for(int i=1; i<n; ++i){
scanf("%d%d%d",&a,&b,&c);
addEdge(a,b,c);
addEdge(b,a,c);
}
dfs1(1,1);
d_up[0][1]=d_up[1][1]=val[1];
dfs2(1,1);
printf("Case #%d:\n",cse);
for(int i=1; i<=n; ++i){
printf("%d\n",max(d_up[0][i]+d_down[1][i],d_up[1][i]+d_down[0][i])-val[i]);
}
}
return 0;
}

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. HDU5834 Magic boy Bi Luo with his excited tree (树形DP)

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

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

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

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

  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. October 4th 2016 Week 41st Tuesday

    Patience! The windmill never strays in search of the wind. 耐心等待!风车从不跑去找风. Sometimes we need to be pa ...

  2. August 24th 2016 Week 35th Wednesday

    Storms make trees take deeper roots. 暴风雨能使大树的根扎得更深. If the trees already have deep roots, then the s ...

  3. 【转】VS项目属性的一些配置项的总结

    首先,解决方案和项目文件夹包含关系(c++项目): VS解决方案和各个项目文件夹以及解决方案和各个项目对应的配置文件包含关系,假设新建一个项目ssyy,解决方案起名fangan,注意解决方案包括项目, ...

  4. [转]DB2时间类函数

    Src URL:http://www.cnblogs.com/wanghonghu/archive/2012/05/25/2518604.html 1.db2可以通过SYSIBM.SYSDUMMY1. ...

  5. js获取url方法

    //设置或获取对象指定的文件名或路径.alert(window.location.pathname); //设置或获取整个 URL 为字符串.alert(window.location.href); ...

  6. Pyqt 获取windows系统中已安装软件列表

    开始之前的基础知识 1. 获取软件列表 在Python的标准库中,_winreg可以操作Windows的注册表.获取已经安装的软件列表一般是读去windows的注册表: SOFTWARE\Micros ...

  7. SQL数据字符串的拆分

    一.概述: MSSQL字符串的拆分没有封装太多常用的方式,所以如果向数据库中插入用特殊字符分割字符串(比如CB0$CB2$CB3,CB0$CB2$CB3)时就可能需要数据库能够分割字符串,SQL中拆分 ...

  8. 【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台

    本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”. 一.预备知识: 1.接口: python中并没有类似java等其它语言中的接口类型,但是python中 ...

  9. 如何在java中使用别人提供的jar包进行导入,编译,运行

    一步一步往前走, 现在折分! JAR包即为上篇文章的东东. 测试JAVA文件. package com.security; import com.security.AESencrp; /** * 实现 ...

  10. 【131031】jsp学习实例 (2013-10-31 15:29:28)

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@ page language= ...