zoukankan      html  css  js  c++  java
  • [HEOI2015]兔子与樱花

    https://zybuluo.com/ysner/note/1218440

    题面

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

    • (nleq2*10^6,mleq10^5)

    解析

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

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

    il void dfs(re int u,re int fa)
    {
      int sta[1000],top=0;c[u]+=k[u];
      for(re int i=h[u];i+1;i=e[i].nxt)
        {
          re int v=e[i].to;
          if(v==fa) continue;
          dfs(v,u);
          sta[++top]=c[v]-1; 
        }
      sort(sta+1,sta+top+1);
      fp(i,1,top) if(c[u]+sta[i]<=m) c[u]+=sta[i],ans++;
      else break;
    }
    

    下面是对比,咕咕咕

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define re register
    #define il inline
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define fp(i,a,b) for(re int i=a;i<=b;i++)
    #define fq(i,a,b) for(re int i=a;i>=b;i--)
    using namespace std;
    const int N=2e6+100;
    struct Edge{int to,nxt;}e[N<<1];
    int n,m,c[N],k[N],h[N],cnt,sz[N],ans,sta[N];
    il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;}
    il ll gi()
    {
      re ll x=0,t=1;
      re char ch=getchar();
      while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    /*强调
    il void dfs(re int u)
    {
      int top=0;c[u]+=k[u];
      for(re int i=h[u];i+1;i=e[i].nxt)
        {
          re int v=e[i].to;
          dfs(v); 
        }
      for(re int i=h[u];i+1;i=e[i].nxt)
        {
          re int v=e[i].to;
          sta[++top]=c[v]-1;
        }
      sort(sta+1,sta+top+1);
      fp(i,1,top) if(c[u]+sta[i]<=m) c[u]+=sta[i],ans++;
      else break;
    }
    */
    int main()
    {
      memset(h,-1,sizeof(h));
      n=gi();m=gi();
      fp(i,1,n) c[i]=gi();
      fp(i,1,n)
        {
          k[i]=gi();
          fp(j,1,k[i])
        {
          re int v=gi()+1;
          add(i,v);
        }
        }
      dfs(1);
      printf("%d
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    [leetCode]101对称二叉树
    UESTC
    UESTC
    UESTC
    Java编程思想 学习笔记12
    Java编程思想 学习笔记11
    Java编程思想 学习笔记10
    Java编程思想 学习笔记9
    Java编程思想 学习笔记8
    Java编程思想 学习笔记7
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9333490.html
Copyright © 2011-2022 走看看