/*
题意:n个点组成的树,点和边都有权值,当第一次访问某个点的时候获得利益为点的权值
每次经过一条边,丢失利益为边的权值。问从第i个点出发,获得的利益最大是多少。
输入:
测试样例组数T
n
n个数每个点的权值
n-1条无向边 a b c a和b是点的标号,c是边的权值。
思路:
注意题目只强调是从某个点出发,并不一定要回到该点。
考虑树形DP。
先随便定义一个树根。然后对于某个点,我们需要维护它子树方向的两个值
1.从该点出发,最终要回到该点的利益的最大值
2.从该点出发,最终不必回到该点的利益的最大值,以及最后一次从该点出发的是哪个儿子节点。
3.从该点出发,最终不必回到该点的利益的第二大值,以及最后一次从该点出发的是哪个儿子节点。
先求出回到该点的利益的最大值,然后枚举它的儿子节点,作为最后出去的节点,即该节点不返回。
第二和第三个值把枚举所有儿子作为最后一次出发的情况然后排序记录下前两个就可以了。
以上是第一次DFS所做的工作。
然后对于每个点维护三个值,进行第二次DFS。
1.从该点出发所有方向(子树方向和父亲方向)回到该点的利益的最大值。
2.从该点出发所有方向,不必回到该点的利益的最大值,并保存最后一个出发的儿子节点的标号。
3.从该点出发所有方向,不必回到该点的利益的第二大值,并保存最后一个出发的儿子节点的标号。
第1个值的维护只需要将子树方向和减掉本身所在子树所影响的父亲方向的值加起来即可。
对于第二个和第三个值,我们可以将子树方向上最大的两个值加上父亲方向回来所带来的利益,与
父亲方向作为最后一次出发的点不回来的利益这三个值中求取两个最大的即可。
之所以要维护第二大的值,是因为当父亲节点最终的答案(即可以不回来)的最后一次访问的点恰
好是我们要求取的它的儿子节点的时候,我们可以用次大的值来确定当该儿子节点的父亲方向作为
最后一次访问的方向的时候的利益。
最后所有的ans[i][1]就是答案。
总结“
1.树形DP维护的时候经常需要维护次大值甚至第三大值,这是由于父亲方向的最优问题是否关系到
儿子节点所决定的。
*/ #include<bits/stdc++.h>
#define N 100050
using namespace std;
struct edge{
int id;
edge *next;
long long w;
};
struct st{
st(int a,long long b){
id=a;
ans=b;
}
long long ans;
int id;
};
bool cmp(st a,st b){
return a.ans>b.ans;
}
int ednum;
edge edges[N*];
edge *adj[N];
long long v[N],son[N][],ans[N][];
int fa[N],id[N][];
inline void addedge(int a,int b,long long w){
edge *tmp=&edges[ednum++];
tmp->w=w;
tmp->id=b;
tmp->next=adj[a];
adj[a]=tmp;
}
void dfs(int pos){
son[pos][]+=v[pos];
for(edge *it=adj[pos];it;it=it->next){
if(fa[pos]!=it->id){
fa[it->id]=pos;
dfs(it->id);
if(son[it->id][]-*it->w>){
son[pos][]+=son[it->id][]-*it->w;
}
}
}
son[pos][]=son[pos][];
vector<st>mv;
mv.push_back(st(,son[pos][]));
mv.push_back(st(,son[pos][]));
for(edge *it=adj[pos];it;it=it->next){
if(fa[it->id]==pos){
if(son[it->id][]-it->w>){
long long tn=son[pos][]+son[it->id][]-it->w;
if(son[it->id][]-*it->w>)tn-=son[it->id][]-*it->w;
if(tn>son[pos][]){
mv.push_back(st(it->id,tn));
}
}
}
}
sort(mv.begin(),mv.end(),cmp);
son[pos][]=mv[].ans;
id[pos][]=mv[].id;
son[pos][]=mv[].ans;
id[pos][]=mv[].id;
}
void dfs2(int pos){
if(pos==){
for(int i=;i<;i++){
ans[pos][i]=son[pos][i];
}
}
for(edge *it=adj[pos];it;it=it->next){
if(fa[it->id]==pos){
long long tans=ans[pos][]-*it->w;
if(son[it->id][]-*it->w>){
tans-=son[it->id][];
tans+=*it->w;
}
tans=max(0LL,tans);
ans[it->id][]=son[it->id][]+tans;
vector<st>mv;
mv.push_back(st(,ans[it->id][]));
mv.push_back(st(,ans[it->id][]));
for(int i=;i<;i++){
mv.push_back(st(id[it->id][i],son[it->id][i]+tans));
}
if(id[pos][]!=it->id){
long long tm=ans[pos][];
tm+=son[it->id][];
if(son[it->id][]-*it->w>){
tm-=son[it->id][]-*it->w;
}
mv.push_back(st(id[pos][],tm-it->w));
}
else{
long long tm=ans[pos][];
tm+=son[it->id][];
if(son[it->id][]-*it->w>){
tm-=son[it->id][]-*it->w;
}
mv.push_back(st(id[pos][],tm-it->w));
}
sort(mv.begin(),mv.end(),cmp);
ans[it->id][]=mv[].ans;
id[it->id][]=mv[].id;
ans[it->id][]=mv[].ans;
id[it->id][]=mv[].id;
dfs2(it->id);
}
}
}
int main()
{
int t;
scanf("%d",&t);
int cas=;
while(t--){
cas++;
printf("Case #%d:\n",cas);
int n;
scanf("%d",&n);
for(int i=;i<=n;i++){
for(int j=;j<;j++){
son[i][j]=id[i][j]=ans[i][j]=;
}
adj[i]=NULL;
fa[i]=;
}
ednum=;
for(int i=;i<=n;i++)scanf("%lld",v+i);
for(int i=;i<n;i++){
int a,b;long long w;
scanf("%d%d%lld",&a,&b,&w);
addedge(a,b,w);
addedge(b,a,w);
}
dfs();
dfs2();
for(int i=;i<=n;i++){
printf("%lld\n",ans[i][]);
}
}
}

HDU 5834 [树形dp]的更多相关文章

  1. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  2. HDU 1520 树形dp裸题

    1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...

  3. HDU 1561 树形DP入门

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  4. HDU 2196树形DP(2个方向)

    HDU 2196 [题目链接]HDU 2196 [题目类型]树形DP(2个方向) &题意: 题意是求树中每个点到所有叶子节点的距离的最大值是多少. &题解: 2次dfs,先把子树的最大 ...

  5. HDU 1520 树形DP入门

    HDU 1520 [题目链接]HDU 1520 [题目类型]树形DP &题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知 ...

  6. codevs 1380/HDU 1520 树形dp

    1380 没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 回到问题 题目描述 Description Ural大学有N个职员 ...

  7. hdu 4267 树形DP

    思路:先dfs一下,找出1,n间的路径长度和价值,回溯时将该路径长度和价值清零.那么对剩下的图就可以直接树形dp求解了. #include<iostream> #include<al ...

  8. hdu 4607 (树形DP)

    当时比赛的时候我们找出来只要求出树的最长的边的节点数ans,如果要访问点的个数n小于ans距离直接就是n-1 如果大于的话就是(n-ans)*2+ans-1,当时求树的直径难倒我们了,都不会树形dp ...

  9. hdu 1520 (树形DP)

    dp[i][0]表示i不参加 dp[i][1]表示i参加 简单的树形dp #include<stdio.h> #include<string.h> #define N 6100 ...

随机推荐

  1. javascript 停止事件冒泡以及阻止默认事件冒泡

    停止事件冒泡 function stopBubble(e) { // 如果提供了事件对象,则这是一个非IE浏览器 if ( e && e.stopPropagation ) { // ...

  2. fetch用法

    fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData)=> { console.log(r ...

  3. servlet & filter & listener & interceptor

    web.xml 的加载顺序是:context- param -> listener -> filter -> servlet * Servlet 对URL生效,用户处理用户的URL请 ...

  4. R提高篇(四): 数据管理二

    目录: 数学函数 统计函数 应用示例 控制流 数学函数 ceiling(x):  大于等于 x  的最小整数, 如:  ceiling(3.213)  --> 4 floor(x):     小 ...

  5. ASP.NET MVC 中实现View与Controller分离

    一.开篇题外话 我经常会在博客园逛来逛去,看过很多大牛们的Blog,我很少在这块技术天地活动,之前有发表过几篇日志,好像大部分是和电商有关,作为一个多年的开发人员,很少在这里分享,之前一直在CSDN上 ...

  6. 纠结的NTP安装过程

    为了部署实验用的openstack环境,其中有NTP的安装环节.在这个过程中,真是折腾了一下午...遇到了一些问题! 由于公司内部网络管理的原因,很多网站没有办法访问,比如公开的时间服务站点,我找了几 ...

  7. [Hibernate] - Select/Update/Delete/Insert

    Java bean: package com.my.bean; import java.util.Date; public class WorkPack { private String uWorkP ...

  8. php 添加redis扩展(二)

    php代码操作redis 1.连接 <?php //连接本地的 Redis 服务 $redis = new Redis(); $redis->connect('127.0.0.1', 63 ...

  9. ssh登录慢,等待输入密码时间长

    有时候在ssh远程登录到其他主机上时发现登录时间太长,要等待很久才会出现输入密码的提示,google了一下,发现主要有两个问题会导致ssh登录慢: 1.使用了dns反查,这样的话当ssh某个IP时,系 ...

  10. android学习笔记24——事件处理

    事件处理 android提供了两种事件处理机制: 1.基于回调的事件处理 2.基于监听器的事件处理(通过绑定特定事件监听器) 注意: android对于基于回调的事件处理而言,主要做法就是重写andr ...