题目链接:
Magic boy Bi Luo with his excited tree
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1037 Accepted Submission(s): 298
Problem Description
Bi Luo is a magic boy, he also has a migic tree, the tree has N nodes , in each node , there is a treasure, it's value is V[i], and for each edge, there is a cost C[i], which means every time you pass the edge i , you need to pay C[i].
You may attention that every V[i] can be taken only once, but for some C[i] , you may cost severial times.
Now, Bi Luo define ans[i] as the most value can Bi Luo gets if Bi Luo starts at node i.
Bi Luo is also an excited boy, now he wants to know every ans[i], can you help him?
You may attention that every V[i] can be taken only once, but for some C[i] , you may cost severial times.
Now, Bi Luo define ans[i] as the most value can Bi Luo gets if Bi Luo starts at node i.
Bi Luo is also an excited boy, now he wants to know every ans[i], can you help him?
Input
First line is a positive integer T(T≤104) , represents there are T test cases.
Four each test:
The first line contain an integer N(N≤105).
The next line contains N integers V[i], which means the treasure’s value of node i(1≤V[i]≤104).
For the next N−1 lines, each contains three integers u,v,c , which means node u and node v are connected by an edge, it's cost is c(1≤c≤104).
You can assume that the sum of N will not exceed 106.
Four each test:
The first line contain an integer N(N≤105).
The next line contains N integers V[i], which means the treasure’s value of node i(1≤V[i]≤104).
For the next N−1 lines, each contains three integers u,v,c , which means node u and node v are connected by an edge, it's cost is c(1≤c≤104).
You can assume that the sum of N will not exceed 106.
Output
For the i-th test case , first output Case #i: in a single line , then output N lines , for the i-th line , output ans[i] in a single line.
Sample Input
1
5
4 1 7 7 7
1 2 6
1 3 1
2 4 8
3 5 2
Sample Output
Case #1:
15
10
14
9
15
题意:
每个节点有价值v[i]的宝物,但是任何两个节点u,v之间的路走一次花费为w,从每个节点出发最多可以赚多少钱;
思路:
树形dp的题目,需要记录转移的最大和次大,注意转移的情况,不能写漏了;
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#include <stack>
#include <map>using namespace std;#define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss));typedef long long LL;template<class T> void read(T&num) {char CH; bool F=false;for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {if(!p) { puts("0"); return; }while(p) stk[++ tp] = p%10, p/=10;while(tp) putchar(stk[tp--] + '0');putchar('\n');
}const int mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=(1<<20)+10;
const int maxn=1e5+110;
const double eps=1e-12;int n,cnt,head[maxn],a[maxn];
int down[maxn][2],up[maxn][2],max1[maxn],max2[maxn],temp[maxn],cost[maxn];
struct Edge
{int from,to,next,val;
}edge[2*maxn];
inline void add_edge(int s,int e,int va)
{edge[cnt].from=s;edge[cnt].to=e;edge[cnt].next=head[s];edge[cnt].val=va;head[s]=cnt++;
}
inline void Init()
{cnt=0;for(int i=0;i<=n;i++)head[i]=-1;
}
void dfs(int cur,int fa,int va)
{down[cur][1]=a[cur];cost[cur]=va;for(int i=head[cur];i!=-1;i=edge[i].next){int x=edge[i].to;if(x==fa)continue;dfs(x,cur,edge[i].val);if(down[x][1]-2*edge[i].val>=0)down[cur][1]+=down[x][1]-2*edge[i].val;}
}
void dfs1(int cur,int fa)
{down[cur][0]=a[cur];temp[cur]=max1[cur]=max2[cur]=0;for(int i=head[cur];i!=-1;i=edge[i].next){int x=edge[i].to;if(x==fa)continue;dfs1(x,cur);if(down[x][0]-edge[i].val>0){int t=down[cur][1];if(down[x][1]-2*edge[i].val>=0)t-=down[x][1]-2*edge[i].val;t+=down[x][0]-edge[i].val;if(t>=down[cur][0]){max2[cur]=max1[cur];temp[cur]=down[cur][0];down[cur][0]=t;max1[cur]=x;}else if(t>temp[cur]){max2[cur]=x;temp[cur]=t;}}}
}void dfs2(int cur,int fa,int va)
{up[cur][1]=0;if(down[cur][1]-2*va>=0)up[cur][1]=max(up[cur][1],down[fa][1]-down[cur][1]+2*va+up[fa][1]-2*va);else up[cur][1]=max(up[cur][1],down[fa][1]+up[fa][1]-2*va);up[cur][0]=0;if(max1[fa]==cur){int t=down[fa][0]-down[cur][0]+va;up[cur][0]=max(up[cur][0],t+up[fa][0]-va);int r=max2[fa];if(down[r][1]-2*cost[r]>0)t=t-down[r][1]+2*cost[r];t+=down[r][0]-cost[r];up[cur][0]=max(up[cur][0],t+up[fa][1]-va);}else {int t=down[fa][0];if(down[cur][1]-2*va>0)t-=down[cur][1]-2*va;up[cur][0]=max(up[cur][0],t+up[fa][1]-va);t=down[fa][1];if(down[cur][1]-2*va>0)t-=down[cur][1]-2*va;up[cur][0]=max(up[cur][0],t+up[fa][0]-va);}for(int i=head[cur];i!=-1;i=edge[i].next){int x=edge[i].to;if(x==fa)continue;dfs2(x,cur,edge[i].val);}
}int main()
{int t,Case=0;read(t);while(t--){read(n);Init();For(i,1,n)read(a[i]);int u,v,w;For(i,1,n-1){read(u);read(v);read(w);add_edge(u,v,w);add_edge(v,u,w);}dfs(1,0,0);dfs1(1,0);dfs2(1,0,0);printf("Case #%d:\n",++Case);for(int i=1;i<=n;i++)printf("%d\n",max(down[i][0]+up[i][1],down[i][1]+up[i][0]));} return 0;
}