宝藏
来源:互联网 发布:2017天猫双11实时数据 编辑:程序博客网 时间:2024/04/28 23:38
题目描述
一棵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
16
提示
对于20%的数据,满足n<=10。对于50%的数据,满足n<=1000。
对于100%的数据,满足1<=n<=3*10^5, 1<=z, ai<=10^5。
显然是一道树形dp题目。考虑回到原点与不回到原点,g[u]表示回到u的最大价值,f[u]表示不回到u的最大价值。显然有g[u]=g[u]+max(0,g[v]-len[i]*2);
f[u]=max{g[u]-g[v]-len[i]+f[v]};
然后考虑根节点的转移,同样记录向上走回与不回的最大值次大值就可以了。详见代码,可能比较丑。
varn,i,u,v,l,tot:longint;head,ret,next,len,g,a:array[-2..800000] of longint;f,p:array[-2..800000,0..2] of longint;procedure ins(u,v,l:longint);begin tot:=tot+1; ret[tot]:=v; len[tot]:=l; next[tot]:=head[u]; head[u]:=tot;end;function max(a,b:longint):longint;begin if a>b then exit(a) else exit(b);end;procedure dfs(u,pre:longint);vari,v,s,t,vv:longint;begin i:=head[u]; g[u]:=a[u]; while i<>0 do begin v:=ret[i]; if v<>pre then begin dfs(v,u); g[u]:=g[u]+max(0,g[v]-len[i]*2); end; i:=next[i]; end; i:=head[u]; f[u,1]:=a[u]; f[u,2]:=a[u]; while i<>0 do begin v:=ret[i]; if (v<>pre) then if g[v]-len[i]*2>0 then begin s:=g[u]-g[v]+f[v,1]+len[i]; vv:=v; if s>f[u,1] then begin t:=vv; vv:=p[u,1]; p[u,1]:=t; t:=s; s:=f[u,1]; f[u,1]:=t; end; if s>f[u,2] then begin p[u,2]:=vv; f[u,2]:=s; end; end else begin s:=g[u]+f[v,1]-len[i]; vv:=v; if s>f[u,1] then begin t:=vv; vv:=p[u,1]; p[u,1]:=t; t:=s; s:=f[u,1]; f[u,1]:=t; end; if s>f[u,2] then begin p[u,2]:=vv; f[u,2]:=s; end; end; i:=next[i]; end;end;procedure find(u,pre,l:longint);vargg,ff,i,v,s,ne,t,k,nex:longint;begin gg:=g[pre]; if g[u]-l*2>0 then gg:=gg-g[u]+l*2; if p[pre,1]<>u then begin ff:=f[pre,1]; ne:=p[pre,1]; if (g[u]-l*2>0) then ff:=ff-g[u]+l*2; end else begin ff:=f[pre,2]; ne:=p[pre,2]; if (g[u]-l*2>0)and(ne<>0) then ff:=ff-g[u]+l*2; end; s:=f[u,1]+gg-2*l; nex:=p[u,1]; if s>f[u,1] then begin t:=nex; nex:=p[u,1]; p[u,1]:=t; t:=s; s:=f[u,1]; f[u,1]:=t; end; if s>f[u,2] then begin p[u,2]:=nex; f[u,2]:=s; end; g[u]:=g[u]+max(0,gg-l*2); if (gg-l*2>0) then begin s:=g[u]-gg+ff+l; if s>f[u,1] then begin t:=ne; ne:=p[u,1]; p[u,1]:=t; t:=s; s:=f[u,1]; f[u,1]:=t; end; if s>f[u,2] then begin p[u,2]:=ne; f[u,2]:=s; end; end else begin s:=g[u]+ff-l; if s>f[u,1] then begin t:=ne; ne:=p[u,1]; p[u,1]:=t; t:=s; s:=f[u,1]; f[u,1]:=t; end; if s>f[u,2] then begin p[u,2]:=ne; f[u,2]:=s; end; end; i:=head[u]; while i<>0 do begin v:=ret[i]; if v<>pre then find(v,u,len[i]); i:=next[i]; end;end;begin readln(n); for i:=1 to n-1 do begin readln(u,v,l); ins(u,v,l); ins(v,u,l); end; for i:=1 to n do read(a[i]); dfs(1,-1); find(1,-1,0); for i:=1 to n do writeln(f[i,1]);end.
0 0
- 宝藏
- 宝藏
- 宝藏
- 宝藏
- 宝藏
- 寻找宝藏
- 收集宝藏
- 探寻宝藏
- NOIP2017D2T2 宝藏
- noip2017宝藏
- 自己就是宝藏
- 艾伦的宝藏
- 世界十大宝藏
- 发现宝藏啦~
- 挖宝藏啦!!
- 挖宝藏 treasures
- 亟待开发的宝藏
- windows核心宝藏
- Android圆形图像的实现。
- 君正JZ4760B-UBoot分析
- Spark MLlib实现的中文文本分类–Native Bayes
- iOS 什么是MVC
- java--学生信息管理
- 宝藏
- MFC Tab Control 选项卡
- 打包出现这个错误Error:A problem was found with the configuration of task ':app:packageRelease'.
- Python-学习笔记(一)
- gcd与lcm
- sublime全程指导
- python下安装opencv碰到的问题
- javah报错找不到类android.graphics.Bitmap
- 并行与并发的区别