就是一个树形分组背包模板。然后最后在、倒叙遍历一遍根节点的dp数组就可以了
#include#include #include #include using std::max;const int maxn=3010;struct node{ int point; int weight; int nxt;};node line[maxn<<1];int head[maxn],tail;void add(int a,int b,int c){ line[++tail].point=b; line[tail].nxt=head[a]; line[tail].weight=c; head[a]=tail;}int cost[maxn];int son[maxn];int f[maxn][maxn];void dfs(int now){ bool has_son=false; f[now][0]=0; for(int i=head[now];i;i=line[i].nxt) { has_son=true; dfs(line[i].point); son[now]+=son[line[i].point]; for(int j=son[now];j>=0;j--) for(int k=0;j-k>=0&&k<=son[line[i].point];k++) f[now][j]=max(f[now][j],f[now][j-k]+f[line[i].point][k]-line[i].weight); } if(!has_son) { son[now]=1; f[now][1]=cost[now]; return ; } return ;}int main(){ memset(f,-10,sizeof(f)); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n-m;i++) { int k,a,b; scanf("%d",&k); for(int j=1;j<=k;j++) { scanf("%d%d",&a,&b); add(i,a,b); } } for(int i=n-m+1;i<=n;i++) scanf("%d",&cost[i]); dfs(1); for(int i=son[1];i>=0;i--) { if(f[1][i]>=0) { printf("%d",i); return 0; } }}