/*
题意: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. memcache 启动参数

    启动方式: 参数 说明 -d 以守护程序(daemon)方式运行 -u root 指定用户,如果当前为 root ,需要使用此参数指定用户 -P /tmp/a.pid 保存PID到指定文件 内存设置: ...

  2. eclipse新建web项目,运行后在tomcat安装目录下webapps中没有该项目

    一.发现问题在eclipse中新建Dynamic Web Project,配置好本地的tomcat并写好代码后选择Run on Server,但运行后发现在tomcat的安装目录下的webapps并没 ...

  3. iText导出pdf、word、图片

    一.前言 在企业的信息系统中,报表处理一直占比较重要的作用,本文将介绍一种生成PDF报表的Java组件--iText.通过在服务器端使用Jsp或JavaBean生成PDF报表,客户端采用超级连接显示或 ...

  4. mysql命令行导入sql文件

    今天从windows上导出一个sql执行文件,再倒入到unbutn中,结果出现乱码,折腾7-8分钟, 解决方式 在导出mysql sql执行文件的时候,指定一下编码格式: 复制代码代码如下: mysq ...

  5. 【shell】read

    read:read命令接收标准输入(键盘)的输入,或其他文件描述符的输入(后面在说).得到输入后,read命令将数据放入一个标准变量中. [参数][变量]  注意:变量要在参数的后面 主要参数: -t ...

  6. 清理SQL Server日志释放文件空间的终极方法

    清理SQL Server日志释放文件空间的终极方法  转自:http://www.cnblogs.com/dudu/archive/2013/04/10/3011416.html [问题场景]有一个数 ...

  7. bzoj2618: [Cqoi2006]凸多边形

    Description 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. Input 第一行有一个整数n,表示凸多边形的个数,以下依 ...

  8. 恢复ext4文件系统superblock

    恢复ext4文件系统superblock 1. Create ext4 文件系统. [root@localhost ~]# mkfs.ext4 /dev/vdb1 [root@localhost ~] ...

  9. Learning Puppet — Resources and the RAL

    Learning Puppet — Resources and the RAL Welcome to Learning Puppet! This series covers the basics of ...

  10. HDMI接口与协议

    深入了解HDMI接口 一.HDMI接口的工作原理这张图是HDMI接口的架构示意图.从左边的信号源中你可以看到,HDMI接口的信源可以是任何支持HDMI输出的设备,而接入端也可以是任何带有HDMI输 入 ...