题意

给你一棵树,边有边权,每经过边一次,就得支付过路费c[i],点上面有宝藏,每个点只能拿一次。

问从每个点出发,能够拿到的最大值是多少?

分析

换根法老祖宗,树形dp必做经典。一上午都献给这题了TAT

分两次dfs进行计算
考虑到从一个点出发的最长路径。两种情况
1.去了儿子回来后,从父亲出去,走到终点。
2.去了父亲回来后,从儿子出去,走到终点。
所以需要分别维护这个点从父亲出去回来和不回来的最大价值,以及从儿子出去回来和不回来的最大价值。
设g[u][0/1]表示从儿子出去回来和不回来 f[u][0/1]表示从父亲出去回来和不回来
g可以从叶节点往根算,但是f需要注意的是,f走出去的最大值的那条路可能是u本身,所以需要维护次大值。

我自己看0和1会看晕,于是这样写dp方程会好很多。
g[u][不回]=max(g[u][不回],g[u][不回]+g[v][回]-2*w) --->在v的子树中绕圈圈后,从u出去,此时u出去的结点是初始值 out[u]=u
g[u][不回]=max(g[u][不回],g[u][回]+g[v][不回]-w) --->在u的子树中绕圈圈后,从v出去,此时u出去的子节点是v,out[u]=v
g[u][回]+=max(0,g[v][回]-2*w ) --->在u的每个有正价值的子树中绕圈圈

当g[v][回]<=2*w 从儿子出去回来的最大价值甚至小于单走到儿子的这条边再回来的花费,不如不走,说明g[u][回]里面没包含走v的情况
f[v][回]=max(f[v][回],f[u][回]+g[u][回]-2*w) --->从v到u,然后在u的父亲、儿子(不包含v)中绕圈圈后,回到v
f[v][不回]=max(f[v][不回],f[u][不回]+g[u][回]-w) --->从v到u,在u的儿子(不包含v)中绕圈圈后,从u的父亲绕圈圈并走到终点
当g[v][回]>2*w
f[v][回]=max(f[v][回],f[u][回]+g[u][回]-g[v][回]) --->从v到u,然后在u的父亲、儿子(包含v)中绕圈圈后,回到v
f[v][不回]=max(f[v][不回],f[u][不回]+g[u][回]-g[v][回]+w) --->从v到u,在u的儿子(包含v)中绕圈圈后,从u的父亲绕圈圈并走到终点

有没有发现上面的不回中只有从u的父亲走到终点,那为什么不可以绕完过后从u的儿子走向终点呢?
其实是可以的,但是这时候你就需要考虑v是不是g[u][不回]的走出去的那个子树呢?
如果是,说明v这个点自己到儿子的价值已经算过了,
枚举u的每个儿子不是v的儿子vk,u和vk间的距离为wk
令tmp=tep=val[u],然后用每个vk更新tmp和tep
tmp=max(tmp,tmp+g[vk][回]-2*wk)
tmp=max(tmp,tep+g[vk][不回]-wk)
tep+=max(0,g[vk][回]-2*wk)
有没有发现这和第一次dfs计算方式很相似?请翻上去类比一下。tmp其实是g[u][不回]的次大值,tep是g[u][回]的次大值。
最后,枚举完所有vk后
f[v][不回]=max(f[v][不回],f[u][回]+tmp-w) --->从v到u,在u的父亲中绕圈圈后,从u(不是v)的儿子走到终点
如果不是,还是分g[u][回]有没有走v讨论
否:f[v][不回]=max(f[v][不回],f[u][回]+g[u][不回]-w) --->从v到u,在u的父亲中绕圈圈,从u(不是v)的儿子绕圈圈(不包含v)并走到终点
是:f[v][不回]=max(f[v][不回],f[u][回]+g[u][不回]-g[v][回]+w) --->从v到u,在u的父亲中绕圈圈,从u(不是v)的儿子绕圈圈(包含v)并走到终点

最后每个点的答案就是max(g[x][回]+f[x][不回],g[x][不回]+f[x][回])

代码

#include<bits/stdc++.h>
using namespace std;
#define N 100010
int t,n,cnt,cas;
int out[N],val[N],pre[N],first[N],f[N][2],g[N][2];
struct email
{int u,v,w;int nxt;
}e[N*4];
inline void add(int u,int v,int w)
{e[++cnt].nxt=first[u];first[u]=cnt;e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
}void dfs(int u,int fa)
{g[u][0]=g[u][1]=val[u];out[u]=u;pre[u]=fa;for(int i=first[u];i;i=e[i].nxt){int v=e[i].v,w=e[i].w;if(v==fa)continue;dfs(v,u);g[u][1]=max(g[u][1],g[u][1]+g[v][0]-2*w);if(g[u][1]<g[u][0]+g[v][1]-w)g[u][1]=g[u][0]+g[v][1]-w,out[u]=v;g[u][0]+=max(0,g[v][0]-2*w);}
}void dfs2(int v,int u,int w)
{if(g[v][0]<=2*w){f[v][0]=max(f[v][0],f[u][0]+g[u][0]-2*w);f[v][1]=max(f[v][1],f[u][1]+g[u][0]-w);}else{f[v][0]=max(f[v][0],f[u][0]+g[u][0]-g[v][0]);f[v][1]=max(f[v][1],f[u][1]+g[u][0]-g[v][0]+w);}if(out[u]==v){int tmp=val[u],tep=val[u];for(int i=first[u];i;i=e[i].nxt){int vk=e[i].v,wk=e[i].w;if(vk==pre[u]||vk==v)continue;tmp=max(tmp,tmp+g[vk][0]-2*wk);tmp=max(tmp,tep+g[vk][1]-wk);tep+=max(0,g[vk][0]-2*wk);}f[v][1]=max(f[v][1],tmp+f[u][0]-w);}else{if(g[v][0]<=2*w)f[v][1]=max(f[v][1],f[u][0]+g[u][1]-w);else f[v][1]=max(f[v][1],f[u][0]+g[u][1]-g[v][0]+w);}for(int i=first[v];i;i=e[i].nxt)if(e[i].v!=u)dfs2(e[i].v,v,e[i].w);
}inline void init()
{cnt=0;cas++;memset(f,0,sizeof(f));memset(g,0,sizeof(g));memset(first,0,sizeof(first));
}int main()
{scanf("%d",&t);while(t--){init();scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&val[i]);for(int i=1;i<n;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}dfs(1,0);dfs2(1,0,0);printf("Case #%d:\n",cas);for(int i=1;i<=n;i++)printf("%d\n",max(f[i][0]+g[i][1],f[i][1]+g[i][0]));}return 0;
}

转载于:https://www.cnblogs.com/NSD-email0820/p/9777993.html

【HDU 5834】Magic boy Bi Luo with his excited tree相关推荐

  1. 『HDU 5834』Magic boy Bi Luo with his excited tree

    转载声明:http://blog.csdn.net/cqu_hyx/article/details/52213912 题目链接:http://acm.hdu.edu.cn/showproblem.ph ...

  2. HDU 5834 Magic boy Bi Luo with his excited tree 树形DP

    Magic boy Bi Luo with his excited tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5834 Descript ...

  3. 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: ...

  4. HDU 5834 Magic boy Bi Luo with his excited tree

    树形dp. 先dfs一次处理子树上的最优解,记录一下回到这个点和不回到这个点的最优解. 然后从上到下可以推出所有答案.细节较多,很容易写错. #pragma comment(linker, " ...

  5. Magic boy Bi Luo with his excited tree

    题意:给出一棵树,给出每个节点的价值以及每条路径的花费,每个节点不论经过多少次只能取一次对应的价值,而每条路径每通过一次都要付出对应的代价.要求输出从每一个节点出发的最大获利. 树形dp. 思路挺显然 ...

  6. 大数加法【HDU 1002】

    大数加法模板 一般的加法只要int类型的两数直接相加即可,大一点的数可以设为long long类型,而超过长整型的数则属于大数问题了,大数加法其实也比较简单,利用数组实现就可以啦: 主要思想如下: ( ...

  7. 【 HDU - 5093】Battle ships(匈牙利算法,二分图匹配)

    题干: Dear contestant, now you are an excellent navy commander, who is responsible of a tough mission ...

  8. 【HDU - 1455】Sticks (dfs + 剪枝)

    题干: George took sticks of the same length and cut them randomly until all parts became at most 50 un ...

  9. 【HDU - 4006】The kth great number (优先队列,求第k大的数)

    题干: Xiao Ming and Xiao Bao are playing a simple Numbers game. In a round Xiao Ming can choose to wri ...

最新文章

  1. TensorFlow基础7-机器学习基础知识(逻辑回归,鸢尾花实现多分类)
  2. Scalable, Distributed Systems Using Akka, Spring Boot, DDD, and Java--转
  3. java头像交互式差分演变_一种基于交互式差分进化计算的用户知识需求获取方法与流程...
  4. 问题 “cell 出栈 selectBox 已选的图标,被释放掉,再次进入屏幕时,没有了已选图标 ” 解决方案...
  5. JZOJ 5379. 【NOIP2017提高A组模拟9.21】Victor爱数字
  6. 风能matlab仿真_发现潜力:使用计算机视觉对可再生风能发电场的主要区域进行分类(第1部分)
  7. linux驱动向不同串口发数据,Linux串口(serial、uart)驱动程序设计
  8. Java 文件目录显示
  9. python面试 hashmap是什么_面试不慌,看完保证让你写HashMap跟玩一样
  10. poj 1276 Cash Machine 背包问题
  11. Java编程:排序算法——希尔排序
  12. 机器学习第六回——无监督学习
  13. AB-PLC软件安装以及授权
  14. windows电脑桌面透明便签待办分类怎么添加
  15. 阿里云对象存储OSS收费标准(很详细一看就懂)
  16. 产品温度冲击检测 VS 实际使用寿命换算详解
  17. 美通企业日报 | 拜耳健康消费品中国研发中心开幕;TCL上半年电视机销量稳居全球第二...
  18. X Server移植指导之三 输出层移植 (XServer Porting Guide)
  19. 【好文】PRD撰写规范
  20. C++面向对象的成绩管理系统(包含菜单和文件输出)

热门文章

  1. ArcGIS Engine空间高效查询(IIdentify方法)
  2. Hadoop综合大作业补交4次作业:获取全部校园新闻,网络爬虫基础练习,中文词频统计,熟悉常用的Linux操作...
  3. 重新想,重新看——CSS3变形,过渡与动画①
  4. (转)static 变量
  5. Requirejs2.0笔记
  6. 编译cegcc 0.59.1
  7. OpenCV中的CV_IMPL是什么意思?
  8. 什么叫单模光纤_什么叫单模光纤_单模光纤的特点是什么
  9. leetcode算法题--Combinations
  10. javascript写滑动图片