题目链接
题目让你求攻打城池能获得的最多宝物,但是攻打城池有顺序,所以,我接图就是把无条件的点接在0节点上,有条件的点按序接在对应的城池上。然后就是背包问题了,取或者不取下面的节点,但是若是要取下面的节点,就意味着该节点一定得取。
完整代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
const int maxN=205;
int N, M, cnt, head[maxN], dp[maxN][maxN];
struct Eddge
{
int to, next, val;
Eddge(int a=0, int b=-1, int c=0):to(a), next(b), val(c) {}
}edge[maxN];
void addEddge(int u, int v, int val)
{
edge[cnt]=Eddge(v, head[u], val);
head[u]=cnt++;
}
int dfs(int u)
{
int son=0;
for(int tmp=head[u]; tmp!=-1; tmp=edge[tmp].next)
{
int v=edge[tmp].to, val=edge[tmp].val, child=0;
son+=( child=dfs(v) );
for(int i=son; i>=1; i--)
{
for(int j=0; j<=child-1; j++)
{
if(i>j) dp[u][i]=max(dp[u][i], dp[u][i-j-1]+dp[v][j]+val);
}
}
}
return son+1;
}
int main()
{
while(scanf("%d%d", &N, &M) && (N | M))
{
memset(head, -1, sizeof(head)); cnt=0; memset(dp, 0, sizeof(dp));
for(int i=1; i<=N; i++)
{
int e1, e2;
scanf("%d%d", &e1, &e2);
addEddge(e1, i, e2);
}
dfs(0);
printf("%d\n", dp[0][M]);
}
return 0;
}