删点这个过程是与顺序无关的,我们不妨从叶子开始删。。考虑一个点x,删去任意孩子对答案贡献是一样的,所以肯定是从负重小的开始删,从root开始dfs,离开一个点时维护一个删完它的子树上的点时的最终负重c[i],那么把x的孩子按c排序贪心地删就可以了。。(为啥n=2000000这样搞不会T掉。。
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 2000005
using namespace std;
struct edge{
int e,next;
}ed[N];
int n,m,i,j,to,ne=0,ans,cnt,a[N],c[N],st[N],f[N];
void add(int s,int e)
{
ed[++ne].e=e;ed[ne].next=a[s];a[s]=ne;
}
void dfs(int x)
{
f[x]=0;int cnt=0;
for (int j=a[x];j;j=ed[j].next)
{
dfs(ed[j].e),c[x]++;
f[x]+=f[ed[j].e];
}
for (int j=a[x];j;j=ed[j].next) st[++cnt]=c[ed[j].e];
sort(st+1,st+1+cnt);
for (int i=1;i<=cnt;i++)
if (c[x]+st[i]-1<=m) c[x]+=st[i]-1,f[x]++;else break;
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) a[i]=0,scanf("%d",&c[i]);
for(i=1;i<=n;i++)
{
- scanf("%d",&cnt);
for (j=1;j<=cnt;j++)
scanf("%d",&to),add(i,++to);
}
ans=0;
dfs(1);
printf("%d\n",f[1]);
}