这题以前好像是做过的。
很容易发现就是treeDP了。
然后需要一点贪心的思想,对于当前以x为根的子树,删除任意的子节点,实际上答案都是+1,所以可以排序一下,然后先删那些值小的点。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int n,m; struct node { int x,y,next; }a[4100000];int len,last[2100000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int ans; int d[2100000],son[2100000]; int tlen,tt[2100000]; void treedp(int x) { for(int k=last[x];k;k=a[k].next)treedp(a[k].y); tlen=0; for(int k=last[x];k;k=a[k].next)tt[++tlen]=d[a[k].y]; sort(tt+1,tt+tlen+1); for(int i=1;i<=tlen;i++) { if(d[x]+tt[i]-1<=m) d[x]=d[x]+tt[i]-1, ans++; else break; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&d[i]); int x; len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) { scanf("%d",&son[i]); for(int j=1;j<=son[i];j++) scanf("%d",&x), ins(i,x+1); d[i]+=son[i]; } ans=0;treedp(1); printf("%d\n",ans); return 0; }