题目链接:

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. JMS学习(一)基本概念

    这两天面试了一两个公司,由于简历中的最近一个项目用到了JMS,然而面试官似乎对这个很感兴趣,所以都被问到了,但可惜的是,我除了说我们使用了JMS外,面对他们提出的一些关于JMS的问题,我回答得相当差, ...

  2. .Net开源项目之开源论坛

    .Net开源项目非常多,但是开源并且直接就能用的BBS项目就很少了,至少最近我在这上面没有找到一个合适的开源论坛.可能是因为我要求比较特殊,不但要开箱即用,还要用MVC+MySql开发. Discuz ...

  3. .NET Core Runtime IDentifier (RID) catalog

    转载至:https://docs.microsoft.com/zh-cn/dotnet/articles/core/rid-catalog What are RIDs? RID is short fo ...

  4. [mysql] 一次sql耗时高引发报警的分析和处理

    1.现象: 最近两天在每天的凌晨0:15-20分左右收到报警短息,报警内容: JDBC-SQL请求最近三分钟内平均耗时时间过高的报警,监控类型:SQL... 2.分析: 从现象来看 每天凌晨15分,可 ...

  5. Android笔记——Windows环境下Android Studio v1.0安装教程

    本文主要讲解Windows环境下Android Studio的安装教程,Mac的Android Studio安装与此类似不在赘述,另外友情提示Windows下的SDK与Mac的SDK是通用的,可以直接 ...

  6. Java中Scanner类和BufferReader类之间的区别

    java.util.Scanner类是一个简单的文本扫描类,它可以解析基本数据类型和字符串.它本质上是使用正则表达式去读取不同的数据类型. Java.io.BufferedReader类为了能够高效的 ...

  7. [Architecture Design] 累进式Domain Layer

    [Architecture Design] 累进式Domain Layer 前言 本篇的内容大幅度的简化了分析设计.面向对象等等相关知识,用以传达累进式Domain Layer的核心概念.实际开发软件 ...

  8. js中创建对象的几种方式

    创建对象指创建一个object并给这个对象添加属性和方法,有以下几个方式: 最基本的: var Person={}; Person.name='tom'; Person.age='20'; Perso ...

  9. jquery实现拖拽以及jquery监听事件的写法

    很久之前写了一个jquery3D楼盘在线选择,这么一个插件,插件很简单,因为后期项目中没有实际用到,因此,有些地方不是很完善,后面也懒得再进行修改维护了.最近放到github上面,但是也少有人问津及s ...

  10. C语言位运算详解

    位运算是指按二进制进行的运算.在系统软件中,常常需要处理二进制位的问题.C语言提供了6个位操作运算符.这些运算符只能用于整形操作数,即只能用于带符号或无符号的char.short.int与long类型 ...