题目链接:

Magic boy Bi Luo with his excited tree

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1037    Accepted Submission(s): 298

Problem 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
 
题意:
 
每个节点有价值v[i]的宝物,但是任何两个节点u,v之间的路走一次花费为w,从每个节点出发最多可以赚多少钱;
 
思路:
 
树形dp的题目,需要记录转移的最大和次大,注意转移的情况,不能写漏了;
 
AC代码:
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#include <stack>
#include <map> using namespace std; #define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss)); typedef long long LL; template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
if(!p) { puts("0"); return; }
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
} const int mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=(1<<20)+10;
const int maxn=1e5+110;
const double eps=1e-12; int n,cnt,head[maxn],a[maxn];
int down[maxn][2],up[maxn][2],max1[maxn],max2[maxn],temp[maxn],cost[maxn];
struct Edge
{
int from,to,next,val;
}edge[2*maxn];
inline void add_edge(int s,int e,int va)
{
edge[cnt].from=s;
edge[cnt].to=e;
edge[cnt].next=head[s];
edge[cnt].val=va;
head[s]=cnt++;
}
inline void Init()
{
cnt=0;
for(int i=0;i<=n;i++)head[i]=-1;
}
void dfs(int cur,int fa,int va)
{
down[cur][1]=a[cur];
cost[cur]=va;
for(int i=head[cur];i!=-1;i=edge[i].next)
{
int x=edge[i].to;
if(x==fa)continue;
dfs(x,cur,edge[i].val);
if(down[x][1]-2*edge[i].val>=0)down[cur][1]+=down[x][1]-2*edge[i].val;
}
}
void dfs1(int cur,int fa)
{
down[cur][0]=a[cur];
temp[cur]=max1[cur]=max2[cur]=0;
for(int i=head[cur];i!=-1;i=edge[i].next)
{
int x=edge[i].to;
if(x==fa)continue;
dfs1(x,cur);
if(down[x][0]-edge[i].val>0)
{
int t=down[cur][1];
if(down[x][1]-2*edge[i].val>=0)t-=down[x][1]-2*edge[i].val;
t+=down[x][0]-edge[i].val;
if(t>=down[cur][0])
{
max2[cur]=max1[cur];
temp[cur]=down[cur][0];
down[cur][0]=t;
max1[cur]=x;
}
else if(t>temp[cur])
{
max2[cur]=x;
temp[cur]=t;
}
}
}
} void dfs2(int cur,int fa,int va)
{
up[cur][1]=0;
if(down[cur][1]-2*va>=0)up[cur][1]=max(up[cur][1],down[fa][1]-down[cur][1]+2*va+up[fa][1]-2*va);
else up[cur][1]=max(up[cur][1],down[fa][1]+up[fa][1]-2*va); up[cur][0]=0;
if(max1[fa]==cur)
{
int t=down[fa][0]-down[cur][0]+va;
up[cur][0]=max(up[cur][0],t+up[fa][0]-va);
int r=max2[fa];
if(down[r][1]-2*cost[r]>0)t=t-down[r][1]+2*cost[r];
t+=down[r][0]-cost[r];
up[cur][0]=max(up[cur][0],t+up[fa][1]-va);
}
else
{ int t=down[fa][0];
if(down[cur][1]-2*va>0)t-=down[cur][1]-2*va;
up[cur][0]=max(up[cur][0],t+up[fa][1]-va);
t=down[fa][1];
if(down[cur][1]-2*va>0)t-=down[cur][1]-2*va;
up[cur][0]=max(up[cur][0],t+up[fa][0]-va);
}
for(int i=head[cur];i!=-1;i=edge[i].next)
{
int x=edge[i].to;
if(x==fa)continue;
dfs2(x,cur,edge[i].val);
}
} int main()
{
int t,Case=0;
read(t);
while(t--)
{
read(n);Init();
For(i,1,n)read(a[i]);
int u,v,w;
For(i,1,n-1)
{
read(u);read(v);read(w);
add_edge(u,v,w);
add_edge(v,u,w);
}
dfs(1,0,0);
dfs1(1,0);
dfs2(1,0,0);
printf("Case #%d:\n",++Case);
for(int i=1;i<=n;i++)printf("%d\n",max(down[i][0]+up[i][1],down[i][1]+up[i][0]));
}
return 0;
}

  

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)

    http://acm.hdu.edu.cn/showproblem.php?pid=5834 题意: 一棵树上每个节点有一个价值$Vi$,每个节点只能获得一次,每走一次一条边要花费$Ci$,问从各个节 ...

  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. mongodb学习2---常用命令解析

    1,mongodb insert()和save()的相同点和区别区别:若新增的数据中存在主键 ,insert() 会提示错误,而save() 则更改原来的内容为新内容.insert({_id : 1, ...

  2. 写给java程序员的c++与java实现的一些重要细微差别

    0.其实常规的逻辑判断结构.工具类.文件读写.控制台读写这些的关系都不大,熟悉之后,这些都是灵活运用的问题. 学习c/c++需要预先知道的一个前提就是,虽然有ANSI C标准,但是每个c/c++编译器 ...

  3. HTML 运算符、类型转换

    1.类型转换: 分为自动转换和强制转换,一般用强制转换. 其他类型转换为整数:parseInt(): 其他类型转换为小数:parseFloat(): 判断是否是一个合法的数字类型:isNaN(): 是 ...

  4. C#知识点总结【1】

    值类型和引用类型 从概念上看,其区别是值类型直接存储其值,引用类型存储值的引用. 在内存当中的状态,值类型存储在堆栈(zhan)中,而引用类型存储在托管堆上. ; int j = i; 上面的例子中 ...

  5. Force.com微信企业号开发系列(一) - 启用二次验证

    微信于9月份推出企业号后引起了业界不小的反响,许多企业都在思索企业号将如何影响企业的运营,从本文开始,我将详细阐述微信企业号开发的相关知识,而本文将着重介绍如何实现更高安全机制的二次验证. 申请企业体 ...

  6. svn 服务器不能看log问题

    Subversion “show log” is offline 1.将/srv/svn/repos/ path svnserve.conf 里的 none-access = read 修改为none ...

  7. IO流-输入输出

    java的I/O技术可以将数据保存到文本.二进制.ZIP压缩文件中,下面来说说一些基本的常识(今天只讲理论).先来说说流,何为流?“流就是一组有序的数据序列,根据操作的类型,可以分为输入(Input) ...

  8. Android项目实战(十):自定义倒计时的TextView

    项目总结 -------------------------------------------------------------------------------------------- 有这 ...

  9. java 的方法注释写在哪里?

    如果有接口,写在接口方法上即可.鼠标滑过方法名时时会显示 如果没有接口,写在每个方法上方. eclipse 分三步 ① 找到方法,并将光标移动至方法名的上方 ②/** ③回车 那,效果是酱紫

  10. 深入理解java虚拟机(1)------内存区域与内存溢出

    在C++领域,关于C++的内存存储,结构等等,有一本书:深度探索C++对象模型,讲解的非常透彻. 而Java确把这一工作交给了虚拟机来处理. 我们首先来看看关于内存的问题. 1.问题: 1)java ...