/*
题意: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. dubbo Linux 解决:nc: command not found

    出现该情况有两种可能: (1)没有配置nc命令的环境变量: (2)该系统没有安装nc命令: 我查看了一下在/usr/bin目录中并没有nc命令,所以我可以认为出现该情况的原因是第二种情况 下载安装 下 ...

  2. postman使用教程

    最近很多朋友在问postman的使用方法,现我经过整理,分享给大家. Postman 是一个很强大的 API调试.Http请求的工具,当你还准备拿着记事本傻傻的去写 Form 表单的时候,你来试试 P ...

  3. MySQL 利用SQL线程对Binlog操作(转)

    背景: 对于MySQL的binlog的查看都是用其自带的工具mysqlbinlog进行操作的,其实还有另一个方法来操作binlog,就是Replication中的SQL线程去操作binlog,其实bi ...

  4. HDP2.4安装(五):集群及组件安装

    HDP(Hortonworks Data Platform)是hortworks推出的100%开源的hadoop发行版本,以YARN 作为其架构中心,包含pig.hive.phoniex.hbase. ...

  5. jquery.find()

    http://www.365mini.com/page/jquery-find.htm

  6. JQuery移除事件

    移除事件 unbind(type [,data])     //data是要移除的函数 $('#btn').unbind("click"); //移除click $('#btn') ...

  7. Func系列4:其他功能

    非Python API接口支持 Func通过非Python API实现远程调用,目的是为第三方工具提供调用及返回接口.Func使用func-transmit命令来实现,支持YAML.JSON格式,实现 ...

  8. 解决RPM包相互依赖的有效方法

    出自:http://blog.csdn.net/kai27ks/article/details/7473683 前言:常用RPM的朋友们都知道,RPM简单易用,但是它的依赖关系是最头疼的!有时候比方说 ...

  9. PYTHON对文件及文件夹的一些操作

    python中对文件.文件夹的操作需要涉及到os模块和shutil模块. 创建文件:1) os.mknod("test.txt") 创建空文件2) open("test. ...

  10. mysql 学习笔记(一)

    查询:show databases; show status; show tables; desc  table-name: 更改root密码:方法一:mysqladmin -uroot -poldp ...