一开始想的都是二维的
dp
。。数据这么大怎么转移啊
QAQ
。
后来发现原来贪心就行辣。。。
直接记
ansi=soni+ci
,那么将这个点删除对应着其父节点
+=ansi−1
那么对于某个点
x
,将儿子的
然后删下面的比删上面的优。
因为删某个点
x
的儿子节点,有影响的只是当前点
考虑
x
的兄弟节点
考虑
另外如果
ansx
增大使得兄弟节点中有至少一个被多删除掉。就算使得
ansfax
相较变大而导致无法删掉,也是不亏的。
所以就可以开开心心的贪心辣!
【代码】
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#define N 2000005
using namespace std;
typedef long long ll;
ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,ans;
int c[N],sz[N];
vector<int>g[N];
bool cmp(int x,int y){
return c[x]<c[y];
}
void Dfs(int x)
{
for(int i=0;i<g[x].size();i++) Dfs(g[x][i]);
sort(g[x].begin(),g[x].end(),cmp);
for(int i=0;i<g[x].size();i++) {
int v=c[g[x][i]];
if(c[x]+v-1<=m) c[x]+=v-1,ans++;
else break;
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++) c[i]=read();
for(int i=1;i<=n;i++)
{
int num=read();c[i]+=num;
for(int j=1;j<=num;j++) g[i].push_back(read()+1);
}
Dfs(1);
printf("%d\n",ans);
return 0;
}