AcWing 1074. 二叉苹果树
考察:树形dp
求保留边后树边权值最大和
思路:
因为选择子节点必须选择父节点,对于一个父节点u,它的两个子节点v1,v2.v1可以选择m条边,那么v2就能选择q-m-1-1条边对于每个一个树的结点,都能这样枚举,所以动态转移方程为f[u][j] = max(f[u][j],f[u][j-k-1]+f[v2][k]+road[i].w) u结点的子结点看成分组背包里的各个小组.一个小组只能选择k个,剩余小组选择剩下的.
此数组实际省略了第几组的信息,所以需要体积需要倒序循环.
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int N = 110; 7 struct Road{ 8 int fr,to,ne,w; 9 }road[N<<1]; 10 int h[N],idx,q,n,f[N][N]; 11 void add(int a,int b,int c) 12 { 13 road[idx].w = c,road[idx].to=b,road[idx].fr = a,road[idx].ne = h[a],h[a] = idx++; 14 } 15 void dfs(int u,int fa) 16 { 17 for(int i=h[u];i!=-1;i=road[i].ne) 18 { 19 int v = road[i].to; 20 if(v==fa) continue; 21 dfs(v,u); 22 for(int j=q;j>=0;j--) 23 for(int k=0;k<j;k++) 24 f[u][j] = max(f[u][j],f[v][k]+f[u][j-1-k]+road[i].w); 25 } 26 } 27 int main() 28 { 29 scanf("%d%d",&n,&q); 30 memset(h,-1,sizeof h); 31 for(int i=1;i<n;i++) 32 { 33 int a,b,c; scanf("%d%d%d",&a,&b,&c); 34 add(a,b,c); add(b,a,c); 35 } 36 dfs(1,-1); 37 printf("%d\n",f[1][q]); 38 return 0; 39 }