通道: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]);
}
}
来源:https://www.cnblogs.com/Rojo/p/4071994.html
