可能做了假題。。。一開始想二維樹形dp,結果發現nm乘起來肯定會掛,然後繼續膜hzwer學長的代碼,發現是道瓜題。。。
考慮這樣一個結論,下面刪點肯定不上面刪點優:
如果一個節點x其子節點可以被刪去,那麼至少可以刪去一個點,貢獻至少爲1,而對於x的父節點毫無影響;而若刪去x節點,從對答案的貢獻上來講也是1,不會更優,而會讓父節點的剩餘空間更小,一定不如刪去x子節點優。
由是從下向上貪心,每次將子節點排序,選擇刪去代價最小的子節點,總複雜度爲O(nlogn)
(貪心策略在考場上根本想不到好嗎。。。)
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=2000005;
int n,m,ans;
int c[maxn];
vector<int>son[maxn];
bool cmp(int a,int b)
{
return c[a]<c[b];
}
void dfs(int x)
{
int sz=son[x].size();
for(int i=0;i<sz;i++)
dfs(son[x][i]);
sort(son[x].begin(),son[x].end(),cmp);
for(int i=0;i<sz;i++)
{
if(c[x]+c[son[x][i]]-1<=m)
{
c[x]+=c[son[x][i]]-1;
ans++;
}
else break;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0,tmp;i<n;i++)
scanf("%d",c+i);
for(int i=0,tmp,temp;i<n;i++)
{
scanf("%d",&tmp);
c[i]+=tmp;
while(tmp--)
{
scanf("%d",&temp);
son[i].push_back(temp);
}
}
dfs(0);
cout<<ans;
return 0;
}