很好的树形DP题目,借鉴了http://www.cppblog.com/Yuan/archive/2010/04/28/113833.html
以后有待于研究下红黑树了
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <map>
#include <string>
#include <sstream>
using namespace std;
#define min(a,b) (((a) < (b)) ? (a) : (b))
const int MAXN = 210;
const int INF = 1e9;
vector<int> tree[MAXN];
int dp[MAXN][MAXN];
int cost[MAXN], node[MAXN];
int n, m;
int dfs(int u)
{
int child = 1;
for (int j = 1; j <= n; ++j)
dp[u][j] = INF;
dp[u][0] = 0;
for (int i = 0; i < tree[u].size(); ++i)
{
int v = tree[u][i];
child += dfs(v);
for (int j = n; j > 0; --j)
for (int k = 0; k <= j; ++k)
dp[u][j] = min(dp[u][j], dp[u][j-k] + dp[v][k]);
}
dp[u][child] = min(dp[u][child], cost[u]);
return child;
}
int main()
{
char str[1000];
while (gets(str) && str[0] != '#')
{
sscanf(str, "%d %d", &n, &m);
for (int i = 0; i <= n; ++i)
tree[i].clear();
map<string, int> mapidx;
int id = 0;
memset(cost, 0, sizeof(cost));
memset(node, 0, sizeof(node));
for (int i = 1; i <= n; ++i)
{
scanf("%s", str);
if (mapidx.find(str) == mapidx.end())
mapidx[str] = ++id;
int u = mapidx[str];
scanf("%d", &cost[u]);
gets(str);
stringstream s(str);
string name;
while (s >> name)
{
if (mapidx.find(name) == mapidx.end())
mapidx[name] = ++id;
tree[u].push_back(mapidx[name]);
++node[mapidx[name]];
}
}
cost[0] = INF;
for (int i = 1; i <= n; ++i)
if (!node[i])
tree[0].push_back(i);
dfs(0);
int ans = INF;
for (int j = m; j <= n; ++j)
if (dp[0][j] < ans)
ans = dp[0][j];
printf("%d\n", ans);
}
return 0;
}