题目大意:ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?
思路:咋一看就想到了依赖背包,依赖关系的时候建个树。dp[i][j]表示以i为根节点的子树加自己选取j个城堡是的最大值,则有dp[u][j] = max(dp[u][j] , dp[u][k] + dp[E[i].v][j-k]);
另外:因为有一个自己加入的根节点0,所以答案是dp[0][m+1].dp时上限是m+1。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 305
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 100000000
int n , m;
struct edge
{
int u , v , w;
int next;
}E[maxn];
int head[maxn];
int dp[maxn][maxn];
int id;
void add(int u , int v , int w)
{
E[id].u = u;
E[id].v = v;
E[id].w = w;
E[id].next = head[u];
head[u] = id++;
}
void solve(int u)
{
// cout << u << " " << head[u] << endl;
if(head[u] < 0) return ;
for(int i = head[u] ; i >= 0 ; i = E[i].next)
{
solve(E[i].v);
for(int j = m ; j > 1 ; j--)
{
for(int k = 1 ; k < j ; k ++)
{
// cout << u << " " << j << " " << k << " " << dp[u][j] << " " << dp[u][k] << " " << E[i].v << " " << dp[E[i].v][j-k]<< endl;
dp[u][j] = max(dp[u][j] , dp[u][k] + dp[E[i].v][j-k]);
// cout << u << " " << j << " " << k << " " << dp[u][j] << " " << dp[u][k] << " " << E[i].v << " " << dp[E[i].v][j-k]<< endl;
}
}
}
}
int main()
{
while(scanf("%d %d" , &n , &m) != EOF && ( n || m))
{
id = 0;
mem(head , -1);
mem(dp , 0);
int a , b;
m++;
for(int i = 1 ; i <= n ; i ++)
{
scanf("%d %d" , &a , &b);
add(a , i , b);
for(int j = 1 ; j <= m ; j ++)
dp[i][j] = b;
// dp[i+1][0] = b;
}
solve(0);
printf("%d\n" , dp[0][m]);
}
return 0;
}