这是一道树形dp,很简单,代码也很好懂。
只要明确几个变量的定义:
f[i][j]:以i为根的树上保留j个结点的最大权值和。
l[i],r[i]:i结点的左右儿子。
剩下的没什么了啊……很好懂啊。
代码提示:
#include<cstdio> #include<iostream> #include<cstring> using namespace std; #define maxn 200 int n,q,map[maxn][maxn],a[maxn],f[maxn][maxn],l[maxn],r[maxn]; void MakeTree(int v) { for(int i=1;i<=n;i++) { if(map[v][i]>=0) { a[i]=map[v][i]; map[v][i]=map[i][v]=-1; l[v]=i; MakeTree(i); break; } } for(int i=1;i<=n;i++) { if(map[v][i]>=0) { a[i]=map[v][i]; map[v][i]=map[i][v]=-1; r[v]=i; MakeTree(i); break; } } } int DP(int i,int j) { if(j==0) return 0; if(l[i]==0&&r[i]==0) return a[i]; if(f[i][j]>0) return f[i][j]; for(int k=0;k<=j-1;k++) f[i][j]=max(f[i][j],DP(l[i],k)+DP(r[i],j-1-k)+a[i]); return f[i][j]; } int main() { scanf("%d%d",&n,&q); q++; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) map[i][j]=-1; for(int i=1;i<=n-1;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); map[x][y]=z; map[y][x]=z; } MakeTree(1); printf("%d",DP(1,q)); return 0; }