题面
https://www.luogu.org/problem/P1273
题解
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,k,w[3050],v,siz[3050];
vector<int> to[3050];
long long f[3050][3050];
struct node{
int bro,son;
} tree[3050];
const long long inf=5e16;
void maketree(int x,int fa) {
int i,l=to[x].size(),t;
for (i=0;i<l;i++) if (to[x][i]!=fa) {
if (tree[x].son==0) {
tree[x].son=to[x][i];
maketree(to[x][i],x);
}
else {
t=tree[x].son;
while (tree[t].bro!=0) t=tree[t].bro;
tree[t].bro=to[x][i];
maketree(to[x][i],x);
}
}
}
void treesum(int x){
if (x>=n-m+1) siz[x]=1; else siz[x]=0;
if (tree[x].bro!=0) {
treesum(tree[x].bro);
siz[x]+=siz[tree[x].bro];
}
if (tree[x].son!=0) {
treesum(tree[x].son);
siz[x]+=siz[tree[x].son];
}
}
void treedp(int x,int d){
int i;
long long dpl,dpr;
if (siz[x]<d) return;
if (f[x][d]<=inf) return;
if (d==0) return;
f[x][d]=inf;
if (tree[x].bro!=0) {
treedp(tree[x].bro,d);
f[x][d]=min(f[x][d],f[tree[x].bro][d]);
}
if (x>=n-m+1) {
for (i=0;i<=d-1;i++) {
if (tree[x].son!=0) {
treedp(tree[x].son,i);
dpl=f[tree[x].son][i];
}
else if (i==0) dpl=0; else dpl=inf/2;
if (tree[x].bro!=0) {
treedp(tree[x].bro,d-1-i);
dpr=f[tree[x].bro][d-1-i];
}
else if (d-1-i==0) dpr=0; else dpr=inf/2;
if (dpl+dpr+w[x]<f[x][d]) f[x][d]=dpl+dpr+w[x];
}
}
else {
for (i=0;i<=d;i++) {
if (tree[x].son!=0) {
treedp(tree[x].son,i);
dpl=f[tree[x].son][i];
}
else if (i==0) dpl=0; else dpl=inf/2;
if (tree[x].bro!=0) {
treedp(tree[x].bro,d-i);
dpr=f[tree[x].bro][d-i];
}
else if (d-i==0) dpr=0; else dpr=inf/2;
if (dpl+dpr+w[x]<f[x][d]) f[x][d]=dpl+dpr+w[x];
}
}
return;
}
int main(){
int i,j,a,c;
scanf("%d %d",&n,&m);
w[1]=0;
for (i=1;i<=n-m;i++) {
scanf("%d",&k);
for (j=1;j<=k;j++) {
scanf("%d %d",&a,&c);
w[a]=c;
to[i].push_back(a);
}
}
for (i=n-m+1;i<=n;i++) {
scanf("%d",&v);
w[i]-=v;
}
maketree(1,0);
treesum(1);
memset(f,1,sizeof(f));
for (i=1;i<=n;i++) f[i][0]=0;
for (i=m;i>=0;i--) {
treedp(1,i);
if (f[1][i]<=0) {
cout<<i<<endl;
return 0;
}
}
}