1 // 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree 2 // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以走多次,问从每个点出发的最大获益 3 // 思路: 4 // dp[i]: 从i点出发回到i点的最大值 5 // d[i][0] 从i点出发不回来的最大值 6 // d[i][1] 从i点出发取最大值的下一个点 7 // d[i][2] 从i点出发取次大值 8 // dfs1处理出这四个 9 // 然后,从1开始转移,分别DP求子节点从父亲转移过来的最大值,和从父亲出去不回来的最大值 10 11 #include <bits/stdc++.h> 12 using namespace std; 13 #define LL long long 14 const double inf = 123456789012345.0; 15 const LL MOD =100000000LL; 16 const int N =1e5+10;; 17 #define clc(a,b) memset(a,b,sizeof(a)) 18 const double eps = 1e-7; 19 void fre() {freopen("in.txt","r",stdin);} 20 void freout() {freopen("out.txt","w",stdout);} 21 inline int read() {int x=0,f=1;char ch=getchar();while(ch>‘9‘||ch<‘0‘) {if(ch==‘-‘) f=-1; ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();}return x*f;} 22 23 vector<pair<int,int> > g[N]; 24 int a[N],ans[N]; 25 int dp[N],d[N][3]; 26 void dfs1(int u,int f){ 27 dp[u]=a[u]; 28 for(int i=0;i<(int)g[u].size();i++){ 29 int v=g[u][i].first; 30 int val=g[u][i].second; 31 if(v==f) continue; 32 dfs1(v,u); 33 dp[u]+=max(0,dp[v]-2*val); 34 } 35 d[u][0]=d[u][2]=a[u]; 36 d[u][1]=-1; 37 for(int i=0;i<(int)g[u].size();i++){ 38 int v=g[u][i].first; 39 int val=g[u][i].second; 40 if(v==f) continue; 41 int tem=dp[u]-max(0,dp[v]-2*val)+max(0,d[v][0]-val);//当前选择路径不回来的最大值 42 if(tem>d[u][0]){ 43 d[u][2]=d[u][0]; 44 d[u][0]=tem; 45 d[u][1]=i; 46 } 47 else if(tem>d[u][2]){ 48 d[u][2]=tem; 49 } 50 } 51 } 52 53 //no从父亲不回来的最大值,yes从父亲回来的最大值 54 void dfs2(int u,int f,int no,int yes){ 55 ans[u]=max(dp[u]+no,yes+d[u][0]); 56 for(int i=0;i<(int)g[u].size();i++){ 57 int v=g[u][i].first; 58 int val=g[u][i].second; 59 if(v==f) continue; 60 int tem1,tem2; 61 if(i==d[u][1]) tem1=max(0,d[u][2]-max(0,dp[v]-2*val));//从父亲出去但不是最优方案的最大值 62 else tem1=max(0,d[u][0]-max(0,dp[v]-2*val)); 63 tem2=max(0,dp[u]-max(0,dp[v]-2*val));//从父亲出去又回来的最大值 64 tem1=max(0,max(tem1+yes-val,tem2+no-val));//儿子节点从父亲转移过来的是 max(父亲儿子节点出去不回来+父亲的父亲出去回来的最大值,父亲儿子节点出去回来+父亲的父亲出去不回来的最大值) 65 tem2=max(0,yes+tem2-2*val); 66 dfs2(v,u,tem1,tem2); 67 } 68 } 69 70 int main(){ 71 int T; 72 scanf("%d",&T); 73 for(int cas=1;cas<=T;cas++){ 74 int n; 75 scanf("%d",&n); 76 for(int i=1;i<=n;i++) g[i].clear(); 77 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 78 for(int i=1;i<n;i++){ 79 int u,v,x; 80 scanf("%d%d%d",&u,&v,&x); 81 g[u].push_back(make_pair(v,x)); 82 g[v].push_back(make_pair(u,x)); 83 } 84 dfs1(1,-1); 85 dfs2(1,-1,0,0); 86 printf("Case #%d:\n",cas); 87 for(int i=1;i<=n;i++) printf("%d\n",ans[i]); 88 } 89 return 0; 90 }
时间: 2024-10-25 06:24:12