题目链接:

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. POJ 1681---Painter's Problem(高斯消元)

    POJ   1681---Painter's Problem(高斯消元) Description There is a square wall which is made of n*n small s ...

  2. [PHP] 命令行执行整合pathinfo模拟定时任务

    命令行模式下,根据传参,调用不同控制器.控制器中根据配置定时执行指定方法 Application.php <?php class Application{ public static funct ...

  3. php正规则表达式的语法

    界定符的三种书写方式: regexpal工具(正规则表达调试工具): 可以实时显示效果出来. 原子: 可见原子,即uincode编码表中的某个字符 不可见原子: 为了避免编码问题导致匹配不正确,要把文 ...

  4. Hibernate之lazy延迟加载(转)

    一.延迟加载的概念 当Hibernate从数据库中加载某个对象时,不加载关联的对象,而只是生成了代理对象,获取使用session中的load的方法(在没有改变lazy属性为false的情况下)获取到的 ...

  5. 【OpenCV】OpenCV中GPU模块使用

    CUDA基本使用方法 在介绍OpenCV中GPU模块使用之前,先回顾下CUDA的一般使用方法,其基本步骤如下: 1.主机代码执行:2.传输数据到GPU:3.确定grid,block大小: 4.调用内核 ...

  6. emulator: ERROR: x86 emulation currently requires hardware acceleration!

    emulator: ERROR: x86 emulation currently requires hardware acceleration!Please ensure Intel  is prop ...

  7. Android项目实战(十一):moveTaskToBack(boolean ) 方法的使用

    当你开发的程序被按后退键退出的时候, 你肯定不想让他就这么被finish()吧,那么就想把程序退置到后台就可. (类似于PC端,你关闭一个浏览器和你最小化一个浏览器的区别) 参看方法:public b ...

  8. 安卓开发_浅谈ContextMenu(上下文菜单)

    长下文菜单,即长按view显示一个菜单栏 与OptionMenu的区别OptionMenu对应的是activity,一个activity只能拥有一个选项菜单ContextMenu对应的是View,每个 ...

  9. eclipse 中手动安装 subversive SVN

    为什么我选择手动安装呢?因为通过 eclipse market 下载实在太慢了.   1.下载离线安装包 http://www.eclipse.org/subversive/latest-releas ...

  10. ip_forward

    查看  cat /proc/sys/net/ipv4/ip_forward 如果是0表示没开启,1表示开启了 临时修改   echo "1" > /proc/sys/net/ ...