在树上做背包。
学到一点:如果想要处理的是树,但是题目中给的是森林的话,可以加一个总的根结点。
A 掉 1011 之后这题就比较顺利的 1A 了。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 220, inf = 0x3f3f3f3f;
int n, m;
int fr[maxn * 2], to[maxn * 2], head[maxn], next[maxn * 2];
int val[maxn], dp[maxn][maxn];
bool vis[maxn];
bool read()
{
if(!(~scanf("%d%d", &n, &m) && (n || m)))
return 0;
int ecnt = 0;
memset(head, -1, sizeof(head));
//memset(isrt, false, sizeof(isrt));
for(int i = 1; i <= n; i++) {
int a;
scanf("%d%d", &a, &val[i]);
fr[ecnt] = a;///0
to[ecnt] = i;
next[ecnt] = head[a];
head[a] = ecnt;
ecnt++;
}
return 1;
}
void dfs(int cur)
{
vis[cur] = true;
for(int i = 1; i <= m+1; i++) dp[cur][i] = val[cur];
for(int i = head[cur]; ~i; i = next[i]) {
int tar = to[i];
if(vis[tar]) continue;
dfs(tar);
for(int j = m+1; j > 0; j--)
for(int k = 1; k < j; k++)
dp[cur][j] = max(dp[cur][j], dp[cur][j-k] + dp[tar][k]);
}
}
void solve()
{
memset(dp, 0, sizeof(dp));
memset(vis, false, sizeof(vis));
dfs(0);
printf("%d\n", dp[0][m+1]);
}
int main()
{
while(read()) {
solve();
}
return 0;
}