[关闭]
@ysner 2018-07-19T00:07:42.000000Z 字数 1545 阅读 1998

[HEOI2015]兔子与樱花

贪心


题面

一棵个点带点权树上,所有点点权和儿子数之和不能超过。每删去一结点,它的父亲将继承该结点的权值和所有儿子。问在满足要求的前提下能删多少个点。

解析

删去一个结点,好处不用说,坏处是父亲可能不能被删了。但是,它父亲的父亲不会受到影响。所以删点顶多以一换一,稳赚不赔。
为了使删点数尽可能多,在每个结点下对儿子贡献排个序,从小取到大即可。

注意统计儿子贡献过程不能与向下递归步骤写在一起。这样下面的贡献会覆盖上面的。

  1. il void dfs(re int u,re int fa)
  2. {
  3. int sta[1000],top=0;c[u]+=k[u];
  4. for(re int i=h[u];i+1;i=e[i].nxt)
  5. {
  6. re int v=e[i].to;
  7. if(v==fa) continue;
  8. dfs(v,u);
  9. sta[++top]=c[v]-1;
  10. }
  11. sort(sta+1,sta+top+1);
  12. fp(i,1,top) if(c[u]+sta[i]<=m) c[u]+=sta[i],ans++;
  13. else break;
  14. }

下面是对比,咕咕咕

  1. // luogu-judger-enable-o2
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<cmath>
  7. #include<algorithm>
  8. #define re register
  9. #define il inline
  10. #define ll long long
  11. #define max(a,b) ((a)>(b)?(a):(b))
  12. #define min(a,b) ((a)<(b)?(a):(b))
  13. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  14. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  15. using namespace std;
  16. const int N=2e6+100;
  17. struct Edge{int to,nxt;}e[N<<1];
  18. int n,m,c[N],k[N],h[N],cnt,sz[N],ans,sta[N];
  19. il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;}
  20. il ll gi()
  21. {
  22. re ll x=0,t=1;
  23. re char ch=getchar();
  24. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  25. if(ch=='-') t=-1,ch=getchar();
  26. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  27. return x*t;
  28. }
  29. /*强调
  30. il void dfs(re int u)
  31. {
  32. int top=0;c[u]+=k[u];
  33. for(re int i=h[u];i+1;i=e[i].nxt)
  34. {
  35. re int v=e[i].to;
  36. dfs(v);
  37. }
  38. for(re int i=h[u];i+1;i=e[i].nxt)
  39. {
  40. re int v=e[i].to;
  41. sta[++top]=c[v]-1;
  42. }
  43. sort(sta+1,sta+top+1);
  44. fp(i,1,top) if(c[u]+sta[i]<=m) c[u]+=sta[i],ans++;
  45. else break;
  46. }
  47. */
  48. int main()
  49. {
  50. memset(h,-1,sizeof(h));
  51. n=gi();m=gi();
  52. fp(i,1,n) c[i]=gi();
  53. fp(i,1,n)
  54. {
  55. k[i]=gi();
  56. fp(j,1,k[i])
  57. {
  58. re int v=gi()+1;
  59. add(i,v);
  60. }
  61. }
  62. dfs(1);
  63. printf("%d\n",ans);
  64. return 0;
  65. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注