超链接
汉语题,树形dp,dp[u][j],表示u点包括u点以下的点一共有j个点被使用了,那么u点与v点是怎么递推的呢,u是v的父节点,u要选择j个,那么从v里选择k个节点,从u里选j-k个节点,组成j个节点。
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <vector>
#include <string>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 205;
const double PI = acos(-1);
const double eps = 1e-8;
const int MOD = 1e9+7;
int n,m;
struct node
{
int to,next;
}edge[MAXN*2];
int tot,head[MAXN];
void init()
{
memset(head,-1,sizeof(head));
tot=0;
}
void add(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int val[MAXN];
int dp[MAXN][MAXN];
void solve(int u)
{
int v;
dp[u][1]=val[u];
for(int i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
solve(v);
for(int j=n;j>=1;j--)
{
for(int k=0;k<j;k++)
{
dp[u][j]=max(dp[u][j],dp[v][k]+dp[u][j-k]);
}
}
}
}
int main()
{
int x,y;
while(scanf("%d%d",&n,&m)!=-1)
{
if(n==0&&m==0)
break;
init();
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
add(x,i);
val[i]=y;
}
memset(dp,0,sizeof(dp));
solve(0);
cout<<dp[0][m+1]<<endl;
}
return 0;
}