宝藏
来源:互联网 发布:奥斯卡终身成就奖 知乎 编辑:程序博客网 时间:2024/04/28 23:48
题目描述
一棵n个点的树,到达一个点会获得这个点上的宝藏,每个宝藏都有一定的价值。经过每条边需要支付一定的过路费。每个点只有一个宝藏,但过路费每次都要交。求从每个点出发能得到的最大收益。
输入
输入文件为treasure.in。
第一行为一个正整数n。
接下来n-1行,每行三个整数x, y, z,描述一条边的两个端点x, y和过路费z。
最后一行n个数,表示每个点上宝藏的价值ai。
输出
输出文件为treasure.out。
输出n行,每行一个数。第i行表示从i出发的最大收益。
样例输入
6
1 2 1
2 3 3
3 4 36
3 6 13
3 5 2
6 8 9 10 13 1
样例输出
30
29
28
10
30
16
提示
对于20%的数据,满足n<=10。
对于50%的数据,满足n<=1000。
对于100%的数据,满足1<=n<=
Solution
travel的升级版,以1为根往下做一遍,往上做一遍。
写的过程真是悲壮感人。。。(话说为什么联考里的dp全是树形的)
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#define ll long longusing namespace std;int n,x,y,z,tot;int head[300005],Next[600005],to[600005],len[600005];int a[300005];ll f[300005],g[300005];//f回到i,g不回到i ll sf[300005],sg[300005]; ll son_down[300005],son_up[300005];void add(int x,int y,int z){ tot++; Next[tot]=head[x]; to[tot]=y; len[tot]=z; head[x]=tot;}void dp(int k,int pre){ f[k]=a[k]; g[k]=a[k]; ll s=0; for(int i=head[k];i!=-1;i=Next[i]) if(to[i]!=pre) { dp(to[i],k); s=s+max(0LL,f[to[i]]-2*len[i]);//去当前子树or不去 } son_down[k]=s; //从底向下做的时候,记录k儿子的信息 f[k]=s+a[k]; //势必要回到i for(int i=head[k];i!=-1;i=Next[i]) if(to[i]!=pre) { ll left=s-max(0LL,f[to[i]]-2*len[i]); //其他子树还要去 g[k]=max(g[k],left+max(g[to[i]],f[to[i]])-len[i]+a[k]); }}void DP(int k,int pre){ ll s=0,left=0; for(int i=head[k];i!=-1;i=Next[i]) if(to[i]!=pre) s=s+max(0LL,f[to[i]]-2*len[i]); s=s+max(0LL,sf[k]); for(int i=head[k];i!=-1;i=Next[i]) if(to[i]!=pre) { left=s-max(0LL,f[to[i]]-2*len[i]); son_up[to[i]]=max(son_up[to[i]],left-2*len[i]); sf[to[i]]=max(sf[to[i]],left-2*len[i]+a[to[i]]); } ll s1=0,s2=0; int p1=0,p2=0; for(int i=head[k];i!=-1;i=Next[i]) if(to[i]!=pre) { left=s-max(0LL,f[to[i]]-2*len[i])+g[to[i]]-len[i]; if(left>s1) { s2=s1; p2=p1; s1=left; p1=to[i]; } else if(left>s2) { s2=left; p2=to[i]; } } left=s-max(0LL,sf[k])+sg[k]; if(left>s1) { s2=s1; p2=p1; s1=left; p1=k; } else if(left>s2) { s2=left; p2=k; } for(int i=head[k];i!=-1;i=Next[i]) if(to[i]!=pre) { if(p1==to[i]) { sg[to[i]]=max(sg[to[i]],s2-len[i]+a[to[i]]-max(0LL,f[to[i]]-2*len[i])); } else { sg[to[i]]=max(sg[to[i]],s1-len[i]+a[to[i]]-max(0LL,f[to[i]]-2*len[i])); } } for(int i=head[k];i!=-1;i=Next[i]) if(to[i]!=pre) DP(to[i],k);}int main(){ cin>>n; for(int i=1;i<=n;i++) head[i]=-1; for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sf[i]=sg[i]=a[i]; } dp(1,0); DP(1,0); for(int i=1;i<=n;i++) printf("%lld\n",max(max(sf[i]+f[i]-a[i],g[i]+son_up[i]),sg[i]+son_down[i])); return 0;}
0 0
- 宝藏
- 宝藏
- 宝藏
- 宝藏
- 宝藏
- 寻找宝藏
- 收集宝藏
- 探寻宝藏
- NOIP2017D2T2 宝藏
- noip2017宝藏
- 自己就是宝藏
- 艾伦的宝藏
- 世界十大宝藏
- 发现宝藏啦~
- 挖宝藏啦!!
- 挖宝藏 treasures
- 亟待开发的宝藏
- windows核心宝藏
- StringUtils类API及使用方法详解
- Android 透明度转换
- CNN-目标检测、定位、分割
- HDU5971【瞎搞】
- NOIP 2016模拟赛[八中题]题解&总结
- 宝藏
- IntelliJ IDEA获取免费使用时间
- 代码风格的简单整理
- [图形学] 布料仿真(质点弹簧模型)
- java集合框架
- 【jsp】 3个编译指令和7个动作指令
- KNN - 笔记(1)
- HBASE我遇坑之client.AsyncProcess: #1, waiting for 5012 actions to finish
- static、初始化代码块