题目链接:
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(' '); } 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: ",++Case); for(int i=1;i<=n;i++)printf("%d ",max(down[i][0]+up[i][1],down[i][1]+up[i][0])); } return 0; }