1. 程式人生 > >BZOJ4027 HEOI2015兔子與櫻花(貪心)

BZOJ4027 HEOI2015兔子與櫻花(貪心)

  首先顯然地如果某個點超過了最大負載,刪掉它仍然是不合法的。刪除某個點當前只會對其父親產生影響,同一個節點的兒子顯然應該按代價從小到大刪。考慮如果刪掉某個點之後他的父親不能再刪了,我們損失了父親這個點,但不會對其他點產生任何影響;而若刪掉父親,其兒子節點中能夠刪除的節點肯定會更少,且會對爺爺造成負面影響。所以我們貪心的自底向下刪點就好了。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include
<algorithm> #include<vector> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 2000010 int n,m,a[N],s[N],t,ans; vector
<int> son[N]; bool cmp(const int&x,const int&y) { return a[x]<a[y]; } void dfs(int k) { int cnt=0; for (int i=0;i<s[k];i++) dfs(son[k][i]); sort(son[k].begin(),son[k].end(),cmp); for (int i=0;i<s[k];i++) if (a[k]+a[son[k][i]]-1<=m) a[k]+=a[son[k][i]]-1
,ans++; else break; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4027.in","r",stdin); freopen("bzoj4027.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<=n;i++) { a[i]+=s[i]=read(); for (int j=1;j<=s[i];j++) son[i].push_back(read()+1); } dfs(1); cout<<ans; return 0; }