码迷,mamicode.com
首页 > 其他好文 > 详细

树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree

时间:2016-08-17 22:54:39      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:

 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 }

 

树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree

标签:

原文地址:http://www.cnblogs.com/ITUPC/p/5782004.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!