题目大意:给你一棵树,每个点都有权值,每条边也有权值,从一个点出发,获得点值,走过一条边付出边值,点值只能获得一次,边值走一次付出一次。问从每个点出发,可以获得的最大价值。
每个点记录从这个点出发又回来的最大值re[x],以及从这个点出发最终往一个方向走的最大值ans[x][0]。第一次dfs还要记录下最优值ans[x][0]、次优值ans[x][1],以及最优值是往那条边走的f[x][0]。第二次dfs就是转移过程,从根节点x到u,对根来说,已经处理好,对u来说第一次dfs是没有往x方向走的,所以第二次dfs要处理掉,既往x方向走又回来取得的值加到原有答案上,还有就是最终走向x方向所取得的值,这里就要用到记录下的最优值ans[x][0]、次优值ans[x][1]。
如果x取得的最大值是走向u方向,那么u走向x就要往x次优值走,如果x取得的最大值不是走向u方向,那么u走向x就要往x最优值走。这样就可以处理出答案了。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
#include <cstring>
#include <vector>
#define make_pair mk
using namespace std;
const int maxn=100000+11111;
int n;
int v[maxn],re[maxn];
int ans[maxn][2];
int f[maxn][2];
struct edge{
int u,w,next;
}e[maxn*2];
int head[maxn];
int cnt;
void add(int u,int v,int w){
e[cnt]=edge{v,w,head[u]};
head[u]=cnt++;
}
inline void read(int &z) {
bool sig=false;
char ch = getchar();
while (ch<'0' || ch>'9') {ch=='-'?sig=true:false;ch = getchar();}
int x = ch - '0';
while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0';
z= sig?-x:x;
}
inline void out(int x){
if(x>9)out(x/10);
putchar(x%10+'0');
}
inline int cal(int x){return x>0?x:0;}
int dfs(int x,int fa){
re[x]=v[x];
for(int i=head[x];i!=-1;i=e[i].next){
int u=e[i].u,w=e[i].w;
if(u==fa)continue;
dfs(u,x);
re[x]+=cal(re[u]-2*w);
}
ans[x][0]=re[x];ans[x][1]=re[x];int f1=-1,f2=-1;
for(int i=head[x];i!=-1;i=e[i].next){
int u=e[i].u,w=e[i].w;
if(u==fa)continue;
int tmp=re[x]-cal(re[u]-2*w)+cal(ans[u][0]-w);
if(tmp>=ans[x][0]){
ans[x][1]=ans[x][0];
ans[x][0]=tmp;
f2=f1;f1=u;
}
else if(tmp>=ans[x][1]){
ans[x][1]=tmp;
f2=u;
}
}
f[x][0]=f1;f[x][1]=f2;
}
int dfs2(int x,int fa){
for(int i=head[x];i!=-1;i=e[i].next){
int u=e[i].u,w=e[i].w;
if(u==fa)continue;
int zz=cal(re[x]-cal(re[u]-2*w)-2*w);
ans[u][0]+=zz;ans[u][1]+=zz;
int haha=0;
if(f[x][0]==u){
haha=cal(ans[x][1]-cal(re[u]-2*w)-w);
}
else {
haha=cal(ans[x][0]-cal(re[u]-2*w)-w);
}
int tmp=re[u]+haha;
if(tmp>=ans[u][0]){
ans[u][1]=ans[u][0];
ans[u][0]=tmp;
f[u][1]=f[u][0];
f[u][0]=x;
}
else if(tmp>=ans[u][1]){
ans[u][1]=tmp;
f[u][1]=x;
}
re[u]+=zz;
dfs2(u,x);
}
}
int main()
{
int t;scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
cnt=1;
scanf("%d",&n);
fill(head,head+n+4,-1);
for(int i=1;i<=n;i++)read(v[i]);
for(int i=1;i<n;i++){
int x,y,w;read(x),read(y),read(w);
add(x,y,w);
add(y,x,w);
}
dfs(1,-1);
dfs2(1,-1);
printf("Case #%d:\n",cas);
for(int i=1;i<=n;i++){
out(ans[i][0]);putchar('\n');
}
}
return 0;
}