树形动规HDU 5834 Magic boy Bi Luo with his excited tree
Posted Coolxxx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树形动规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,除了以上的情况还有可能是往它的父亲方向走,这里就分两种,一种是走父亲那边再回来走自己的子树,还有一种是走自己的子树再回来走父亲那边
(肯定最后都不会特意回到u,因为边权>0,回到自己不会更优)而这些状态都可以通过dfs里求得f和g推出。
具体推法我已写在代码注释中,希望没有写错。。
1 // 2 //by coolxxx 3 //#include<bits/stdc++.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<map> 9 #include<stack> 10 #include<queue> 11 #include<set> 12 #include<bitset> 13 #include<memory.h> 14 #include<time.h> 15 #include<stdio.h> 16 #include<stdlib.h> 17 #include<string.h> 18 //#include<stdbool.h> 19 #include<math.h> 20 #define min(a,b) ((a)<(b)?(a):(b)) 21 #define max(a,b) ((a)>(b)?(a):(b)) 22 #define abs(a) ((a)>0?(a):(-(a))) 23 #define lowbit(a) (a&(-a)) 24 #define sqr(a) ((a)*(a)) 25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) 26 #define mem(a,b) memset(a,b,sizeof(a)) 27 #define eps (1e-8) 28 #define J 10 29 #define mod 1000000007 30 #define MAX 0x7f7f7f7f 31 #define PI 3.14159265358979323 32 #define N 100004 33 using namespace std; 34 typedef long long LL; 35 int cas,cass; 36 int n,m,lll,ans; 37 int w[N],last[N],g[N]; 38 int f[2][N],from[3][N],h[3][N]; 39 struct xxx 40 { 41 int next,to,d; 42 }a[N+N]; 43 bool mark[N]; 44 void add(int x,int y,int z) 45 { 46 a[++lll].d=z; 47 a[lll].to=y; 48 a[lll].next=last[x]; 49 last[x]=lll; 50 } 51 void dfs(int u,int fa)//从根开始往下走的解 52 { 53 int i,j,v; 54 g[u]=w[u]; 55 for(i=last[u];i;i=a[i].next) 56 { 57 v=a[i].to; 58 if(v==fa)continue; 59 dfs(v,u); 60 g[u]+=max(0,g[v]-a[i].d-a[i].d);//g[u]统计最后回到u的最优解 61 } 62 for(i=last[u];i;i=a[i].next) 63 { 64 v=a[i].to; 65 if(v==fa || f[0][v]<=a[i].d)continue; 66 j=g[u]-max(0,g[v]-a[i].d-a[i].d)+max(0,f[0][v]-a[i].d); 67 //枚举从u哪一条走下去不回,如果g[u]计算时有走v则要扣掉,再加上选择走v不回的最优值 68 if(f[0][u]<=j)//不回u的最优值 69 { 70 f[1][u]=f[0][u],from[1][u]=from[0][u]; 71 f[0][u]=j,from[0][u]=i; 72 } 73 else if(f[1][u]<j)//不回u的次优值 74 f[1][u]=j,from[1][u]=i; 75 } 76 f[0][u]=max(f[0][u],g[u]); 77 f[1][u]=max(f[1][u],g[u]); 78 } 79 void work(int u,int fa)//计算最后答案 80 { 81 int i,j,v; 82 for(i=last[u];i;i=a[i].next) 83 { 84 v=a[i].to; 85 if(v==fa)return; 86 j=max(0,g[v]-a[i].d-a[i].d);//u走到v再走回来是否更优 87 h[0][v]=f[0][v]+max(0,g[u]-j-a[i].d-a[i].d);//g[u]扣除掉走v子树的值,先从v向上走到u再从u走回来,然后走回v的最优值 88 h[1][v]=f[1][v]+max(0,g[u]-j-a[i].d-a[i].d);//次优值 89 from[2][v]=i; 90 if(g[v]>=a[i].d+a[i].d)//这种情况下前面多扣了一次边权 91 { 92 if(from[0][u]!=i)h[2][v]=h[0][u]+a[i].d;//v往上走回头再往下走不回头 93 else h[2][v]=h[1][u]+a[i].d;//当前是最优值,选另一条走次优值 94 } 95 else//前面少扣了一次边权 96 { 97 if(from[0][u]!=i)h[2][v]=h[0][u]+g[v]-a[i].d;//v往下走回头再往上走不回头 98 else h[2][v]=h[1][u]+g[v]-a[i].d; 99 } 100 if(h[2][v]>h[1][v])swap(h[2][v],h[1][v]),swap(from[2][v],from[1][v]); 101 if(h[1][v]>h[0][v])swap(h[1][v],h[0][v]),swap(from[1][v],from[0][v]); 102 g[v]+=max(0,g[u]-j-a[i].d-a[i].d);//更新答案 103 work(v,u); 104 } 105 } 106 int main() 107 { 108 #ifndef ONLINE_JUDGE 109 // freopen("1.txt","r",stdin); 110 // freopen("2.txt","w",stdout); 111 #endif 112 int i,j,k; 113 int x,y,z; 114 // for(scanf("%d",&cass);cass;cass--) 115 for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 116 // while(~scanf("%s",s+1)) 117 // while(~scanf("%d",&n)) 118 { 119 mem(f,0);mem(from,0);mem(last,0);lll=0; 120 printf("Case #%d:\\n",cass); 121 scanf("%d",&n); 122 for(i=1;i<=n;i++) 123 scanf("%d",&w[i]); 124 for(i=1;i<n;i++) 125 { 126 scanf("%d%d%d",&x,&y,&z); 127 add(x,y,z); 128 add(y,x,z); 129 } 130 dfs(1,0); 131 h[0][1]=f[0][1],h[1][1]=f[1][1]; 132 work(1,0); 133 for(i=1;i<=n;i++) 134 printf("%d\\n",h[0][i]); 135 } 136 return 0; 137 } 138 /* 139 // 140 141 // 142 */
以上是关于树形动规HDU 5834 Magic boy Bi Luo with his excited tree的主要内容,如果未能解决你的问题,请参考以下文章
hdu5834 Magic boy Bi Luo with his excited tree 树形dp
HDU 5834 Magic boy Bi Luo with his excited tree (树形DP)
Magic boy Bi Luo with his excited tree (树形dp)
2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree