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

 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

树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree的相关文章

动态规划(树形DP):HDU 5834 Magic boy Bi Luo with his excited tree

非常难想的树形DP. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int N=100010; 6 int cnt,fir[N],nxt[N*2],to[N*2],val[N*2]; 7 int n,w[N],ans[N],fa[N],f1[N][2],f2[N][2]; 8 void addedge(int a,int b,in

hdu5834 Magic boy Bi Luo with his excited tree(树形dp)

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): 723    Accepted Submission(s): 192 Problem Description Bi Luo is a magic boy, he also has a migic tree,

2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree

Magic boy Bi Luo with his excited tree 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

hdu5834 Magic boy Bi Luo with his excited tree 【树形dp】

题目链接 hdu5834 题解 思路很粗犷,实现很难受 设\(f[i][0|1]\)表示向子树走回来或不回来的最大收益 设\(g[i][0|1]\)表示向父亲走走回来或不回来的最大收益 再设\(h[i]\)为\(f[i][0]\)的次优收益 对于\(f[i][1]\),贪心选择所有\(f[v][1] - 2 * w \ge 0\)的子树即可 对于\(f[i][0]\),贪心选择所有没有被选的子树的\(f[v][0] - w \le 0\)的最大值 或者 被选子树\(f[v][1] - 2 * w

&lt;hdu5834 Magic boy Bi Luo with his excited tree&gt; (树形DP)

题意:一棵树有点权和边权 从每个点出发 走过一条边要花费边权同时可以获得点权 边走几次就算几次花费 点权最多算一次 问每个点能获得的最大价值 题解:好吧 这才叫树形DP入门题 dp[i][0]表示从i节点的儿子中走又回到i的最大值 dp[i][1]表示不回到i的最大值 dp[i][2]表示不回到i的次大值 同时需要记录不回到i最大值的方向id[x] 很显然 第一遍dfs可以预处理每个节点往下的值 然后关键的就是每个节点从父亲这个方向的值怎么处理 有个很显然的结论就是 不回来是肯定比回来更优的 所

【树形动规】HDU 5834 Magic boy Bi Luo with his excited tree

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5834 题目大意: 一棵N个点的有根树,每个节点有价值ci,每条树边有费用di,节点的值只能取一次,边权每次经过都要扣,问从每一个节点开始走最大能获得的价值. 题目思路: [树形动态规划] 首先用dfs求出从根1往下走的:节点u往下走最后回到节点u的最大值g[u],节点u往下走最后不回到u的最优值和次优值f[0][u],f[1][u] 接着考虑一个节点u,除了以上的情况还有可能是往它的父亲方向走,这

hdu 5834 Magic boy Bi Luo with his excited tree 树形dp+转移

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): 1058    Accepted Submission(s): 308 Problem Description Bi Luo is a magic boy, he also has a migic tree,

【HDOJ 5834】Magic boy Bi Luo with his excited tree(树型DP)

[HDOJ 5834]Magic boy Bi Luo with his excited tree(树型DP) Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Bi Luo is a magic boy, he also has a migic tree,

HDU 5834 Magic boy Bi Luo with his excited tree

题目:Magic boy Bi Luo with his excited tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5834 题意:给一棵树,在树的每个结点可以收获一定的积分,每一条边会消耗一定的积分,每个结点积分取一次便完,但每次路过一条边,都会消耗积分,问从每一个结点出发,最多能捞多少积分.N范围10万,样例数1万. 思路: 不难的一道题,但细节较多,容易出错. 树形DP. 从i 点出发,大致可以分为向上 和 向下两种,先考虑向下的情