洛谷 2015 二叉苹果树
【题解】
经典的树形DP,这里补一下题解。
我们可以把边权转化为点权,设f[i][j]为i节点,保留了j个节点的最大价值。
那么转移就是f[i][j]=max(f[i][j],f[i][j-k]+f[to][k]),其中f[i][1]为i点的父亲到它的边的边权,我们转化为i的点权。
每个点要强制取它自己,才能从它的孩子转移,但是1号点除外,因为只要1号点的话不需要保留任何的边。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define LL long long 5 #define rg register 6 #define N 200 7 using namespace std; 8 int n,m,tot,last[N],f[N][N]; 9 struct edge{ 10 int to,pre,w; 11 }e[N<<1]; 12 inline int read(){ 13 int k=0,f=1; char c=getchar(); 14 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 15 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 16 return k*f; 17 } 18 void dfs(int x,int fa){ 19 for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa){ 20 f[to][1]=e[i].w; dfs(to,x); 21 } 22 for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa){ 23 for(rg int j=m;j;j--) 24 for(rg int k=(x==1?j:j-1);k;k--) f[x][j]=max(f[x][j],f[x][j-k]+f[to][k]); 25 } 26 } 27 int main(){ 28 n=read(); m=read(); 29 for(rg int i=1;i<n;i++){ 30 int u=read(),v=read(),w=read(); 31 e[++tot]=(edge){u,last[v],w}; last[v]=tot; 32 e[++tot]=(edge){v,last[u],w}; last[u]=tot; 33 } 34 dfs(1,0); 35 printf("%d\n",f[1][m]); 36 return 0; 37 } 38