题面
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; } } }