BZOJ 4027 HEOI2015 兔子与樱花 树形贪心

题目大意:给定一棵有根树,每个点上有一些樱花,现在要求删除一些节点,删除节点的樱花和子节点都会连到父节点上,要求每个节点的樱花数+子节点数不超过,求最多删多少个节点

这数据范围也只能贪心了吧= = 令号节点的最小负重 那么首先对于每个节点我们对于所有的子节点为根的子树尽量删,,然后考虑如何删除子节点 对于节点 因此我们对排序,从小到大取即可

为什么这是对的呢? 我们考虑一棵子树对父节点的影响只有删除子树的根时根上的东西会被塞到父节点上去 那么一棵子树如果删的不是最多,那么能产生的好处只有删除根时塞到父亲节点上的东西少一些 这样做的最终收益只有【根节点由不可删变为可删】 结果我还莫不如不删根节点,然后让子树中多删一些呢= =

因此贪心是对的。

;struct abcd{int to,next;}table[M];int head[M],tot;int n,m;int a[M],f[M],g[M];bool not_root[M];void Add(int x,int y){table[++tot].to=y;table[tot].next=head[x];head[x]=tot;}void Tree_Greedy(int x){int i,top=0;for(i=head[x];i;i=table[i].next){Tree_Greedy(table[i].to);f[x]+=f[table[i].to];g[x]++;}[M];g[x]+=a[x];for(i=head[x];i;i=table[i].next)stack[++top]=g[table[i].to]-1;sort(stack+1,stack+top+1);for(i=1;i<=top;i++)if(g[x]+stack[i]<=m)f[x]++,g[x]+=stack[i];elsebreak;}int main(){int i,j,k,x;cin>>n>>m;for(i=1;i<=n;i++)scanf(“%d”,&a[i]);for(i=1;i<=n;i++){scanf(“%d”,&k);for(j=1;j<=k;j++){scanf(“%d”,&x);Add(i,++x);not_root[x]=true;}}for(i=1;i<=n;i++)if(!not_root[i]){Tree_Greedy(i);cout<<f[i]<<endl;return 0;}return 0;}

天再高又怎样,踮起脚尖就更接近阳光。

BZOJ 4027 HEOI2015 兔子与樱花 树形贪心

相关文章:

你感兴趣的文章:

标签云: