【树形DP】HDU 1561 The more, The Better
通道:http://acm.hdu.edu.cn/showproblem.php?pid=1561
题意:有依赖关系的点权森林,求选m个点权和最大。
思路:dp[i][j]:i子树选j个节点,dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[son[i]][k]),森林的处理就是增加一个点即可。
代码:
#include<stdio.h> #include<string.h> #define N 205 int n,m,edgeNum=0; int ans[N],dp[N][N]; int visit[N],head[N]; struct Line{int v,next;}edge[N]; int max(int a,int b){return a>b?a:b;} void add(int u,int v) { edge[edgeNum].v=v; edge[edgeNum].next=head[u]; head[u]=edgeNum++; } void dfs(int root) { visit[root]=1; for(int i=head[root];i!=-1;i=edge[i].next) { int u=edge[i].v; if(!visit[u]) { dfs(u); for(int k=m;k>=0;k--) for(int j=0;j<=k;j++) dp[root][k+1]=max(dp[root][k+1],dp[root][k-j+1]+dp[u][j]); } } } int main() { int a,b; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; edgeNum=ans[0]=0; memset(dp,0,sizeof(dp)); memset(head,-1,sizeof(head)); memset(visit,0,sizeof(visit)); for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b); ans[i]=b; add(a,i); dp[i][1] = b; } dfs(0); printf("%d\n",dp[0][m+1]); } }