很显然吧,直接做树形dp
两维
以什么为根的子树
选择多少个用户
所能得到的最大价值
注意 中转站不算
直接在转移的时候维护一下就好了
#include<bits/stdc++.h>
#define MAXN 3000
using namespace std;
//f[i][j]以i为根的子树选取j个用户的最大利润
//f[i][j] = max(f[i][j] , f[i][k]+f[s][j-k]-cost(i,s)[s是i的儿子])
int n,m,tot,maxl;
int h[MAXN+5],num[MAXN+5],f[MAXN+5][MAXN+5],sz[MAXN+5];
struct node{
int from,to,cost,next;
}e[MAXN<<1+5];
void init(){
tot = 0;
memset(h , -1 , sizeof(h));
memset(num , 0 , sizeof(num));
}
void add(int x , int y , int z){
tot++;
e[tot].from = x;
e[tot].to = y;
e[tot].cost = z;
e[tot].next = h[x];
h[x] = tot;
}
int dfs(int now){
f[now][0]=0;
for(int i = h[now] ; i != (-1) ; i = e[i].next){
dfs(e[i].to);sz[now] += sz[e[i].to];
for(int j = sz[now] ; j > 0 ; j--){
for(int k = 1 ; k <= sz[e[i].to] ; k++){
f[now][j] = max(f[now][j] ,f[now][j-k] + f[e[i].to][k] - e[i].cost);
}
}
}
}
int main(){
init();
cin>>n>>m;
for(int i = 1 ; i<= n - m ; i++){
int k,a,c;cin>>k;
for(int j = 1 ; j <= k ; j++){
cin>>a>>c;
add(i , a , c);
}
}
for(int i = n - m + 1 ; i <= n ; i++)sz[i] = 1;
for(int i =1; i<=n;i++)for(int j=1;j<=n;j++)f[i][j] = -9999999;
for(int i = n - m + 1 ; i <= n ; i++)cin>>f[i][1];
dfs(1);
int maxl=0;
for(int i=0;i<=m;i++)if(f[1][i]>=0)maxl = i;
cout<<maxl<<endl;
}