题目:click
每个城堡被攻克,必须之前有一个特定的城堡被攻克,才能攻占这个城堡。
形成了一种子节点与父节点的关系,联想到树形dp取解决。
走子节点必先走其父亲节点,一次建树,若无则父亲节点为0;
dp[i][j]:表示以i为节点,取j个城堡宝藏获得的最大值。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<map>
#include<algorithm>
#include<queue>
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
int dp[210][210];// 第i个节点 收集了j个 的最大值
vector<int>hh[210];
int a[210];
int n,m;
bool vis[210];
void dfs(int root)
{
if(vis[root])
return ;
vis[root]=true;
dp[root][1]=a[root];
for(int i=0;i<hh[root].size();i++)
{
int v=hh[root][i];
if(vis[v])
continue;
dfs(v);
for(int j=m+1;j>=2;j--)
{
for(int k=1;k<j;k++)
dp[root][j]=max(dp[root][j],dp[root][j-k]+dp[v][k]);
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)&&(n||m))
{
memset(vis,false,sizeof(vis));
memset(dp,0,sizeof(dp));
a[0]=0;
int i,j,k;
for(i=0;i<=n;i++)
hh[i].clear();
for(i=1;i<=n;i++)
{
int x;
scanf("%d %d",&x,&a[i]);
{
hh[i].push_back(x);
hh[x].push_back(i);
}
}
dfs(0);
printf("%d\n",dp[0][m+1]);
}
return 0;
}