dp[i][j] 代表第i个点获取j个体积所需最小价值,
每个物品的体积就是它所支配的子节点的数量,价值就是它的点值了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<map>
#include<vector>
#define maxn 205
using namespace std;
map<string , int> mp;
vector<int> ve[1000];
int num[maxn], dp[maxn][maxn], va[maxn];
int on[maxn];
int n, m, cnt;
using namespace std;
void dfs(int pre)
{
num[pre] = 1;
for(int i = 0; i < ve[pre].size(); i++)
{
int pre2 = ve[pre][i];
dfs(pre2);
num[pre] += num[pre2];
for(int j = n; j>= 0; j--)
{
if(num[pre2] <= j) dp[pre][j] = min(dp[pre][j], dp[pre][j - num[pre2]] + va[pre2]);
for(int k = j; k >= 0; k--)
dp[pre][j] = min(dp[pre][j], dp[pre][j - k] + dp[pre2][k]);
}
}
}
int main()
{
char s[1005];
while(gets(s))
{
if(s[0] == '#')break;
sscanf(s,"%d%d",&n,&m);
mp.clear();
for(int i = 0; i<= n; i++) ve[i].clear();
for(int i = 0; i <= n; i++)
for(int j = 1; j <= n; j++) dp[i][j] = 99999999;
memset(on, 0, sizeof(on));
cnt = 1;
va[0] = 99999999;
for(int i = 1; i<= n; i++)
{
string a;
int b;
cin >> a >> b;
if(!mp[a]) mp[a] = cnt++;
int pre = mp[a];
va[pre] = b;
while(getchar()!='\n')
{
cin >> a;
if(!mp[a]) mp[a] = cnt++;
ve[pre].push_back(mp[a]);
on[mp[a]]++;
}
}
for(int i = 1; i <= n; i++) if(!on[i]) ve[0].push_back(i);
dfs(0);
int ans = 99999999;
for(int i = m; i<= n; i++) ans = min(ans, dp[0][i]);
printf("%d\n", ans);
}
return 0;
}
/*
5 2
a 123 b c d e
b 1
c 2
d 3
e 4
*/