不T不M无玄学,但是WA声一片,球球汁源TAT
以下代码(含注释):
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e3+5;
struct edge{
int val;
int to;
}fa[2*maxn];
int con[maxn];
int dp[maxn][maxn];//from node x select y (son) nodes with least cost or most earning.
vector<int>v[maxn];
int sz[maxn];
void conn(int a,int b,int w){//building tree (single_direction edge & father relation)
fa[b].val=w;
fa[b].to=a;
v[a].push_back(b);
return ;
}
int n,m;
void dfs(int x){//calculate leaves in sz[x]
if(x>n-m)sz[x]=1;
else sz[x]=0;
for(int i=0;i<v[x].size();i++){
int now=v[x][i];
dfs(now);
sz[x]+=sz[now];
}
return ;
}
int acum[maxn];//temporarily recording number of leaves before
void deal(int x){
//printf("Now scanning node %d (father node: %d)\n",x,fa[x].to);
int fa_=fa[x].to;
for(int i=sz[x];i>=1;i--){
for(int j=acum[fa_];j>=0;j--){
int neww=dp[fa_][j]+dp[x][i]-fa[x].val;
if(neww>dp[fa_][i+j]){
dp[fa_][i+j]=neww;
//printf("node %d's leaves %d data now updated to %d. (Choosing %d nodes from %d, costing %d to pass)\n",fa_,j+i,dp[fa_][j+i],i,x,fa[x].val);
}
}
}
acum[fa_]+=sz[x];
con[fa_]--;
if(con[fa_]==0 && fa_!=1)deal(fa_);
return ;
}
int main(){
// freopen("test1.txt","r",stdin);
// freopen("testout.txt","w",stdout);
int cnt=0;
scanf("%d %d",&n,&m);
for(int i=1;i<=n-m;i++){
scanf("%d",&con[i]);
for(int j=1;j<=con[i];j++){
cnt++;
int t,w;
scanf("%d %d",&t,&w);
conn(i,t,w);
}
}
for(int i=1;i<=n;i++){
if(i<=n-m){
for(int j=1;j<=m;j++){
dp[i][j]=-2e9;
}
}
else{
scanf("%d",&dp[i][1]);
}
}
dfs(1);
for(int i=n-m+1;i<=n;i++){
deal(i);
}
for(int i=m;i>=0;i--){
if(dp[1][i]>=0){
printf("%d",i);
break;
}
}
return 0;
}