zoukankan      html  css  js  c++  java
  • BZOJ 4027 [HEOI 2015] 兔子与樱花 解题报告

    这个题看起来好神的感觉。实际上也好神。。。

    我们可以考虑设 $f_u$ 表示以 $u$ 为根的子树中最多能删多少个点,

    再设 $g_u$ 表示以 $u$ 为根的子树中删了 $f_u$ 个点之后,$u$ 的 $son(i) + c_i$ 的最小值。

    然后就可以树形 Dp 啦。

    转移的话,考虑 $u$ 的孙子及更后辈,有:

    $$f_u += sum_{vin {son_u}}f_v$$

    然后考虑可以 $u$ 的哪些儿子。

    首先删掉一个点 $x$ 的话,会对 $fa_x$ 的载重产生 $g_x - 1$ 点个贡献,

    所以我们就按照这个贡献来排序,然后贪心地从小到大来选择是否删掉这个点。

    那么我们就能够对 $f_u$ 和 $g_u$ 进行转移了。

    时间复杂度 $O(nlog n)$,应该是可以过的吧。。。

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 #define N 2000000 + 5
     8  
     9 int n, m, tot;
    10 int C[N], Size[N], Head[N], F[N], G[N], q[N], T[N];
    11  
    12 struct Edge
    13 {
    14     int next, node;
    15 }h[N];
    16  
    17 inline void addedge(int u, int v)
    18 {
    19     h[++ tot].next = Head[u];
    20     Head[u] = tot;
    21     h[tot].node = v;
    22 }
    23  
    24 inline int getint()
    25 {
    26     char ch = '
    ';
    27     for (; ch > '9' || ch < '0'; ch = getchar()) ;
    28     int res = ch - '0';
    29     for (ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar())
    30         res = (res << 3) + (res << 1) + ch - '0';
    31     return res;
    32 }
    33  
    34 inline void Solve()
    35 {
    36     int l = 1, r = 1;
    37     q[1] = 0;
    38     while (l <= r)
    39     {
    40         int z = q[l ++];
    41         for (int i = Head[z]; i; i = h[i].next)
    42         {
    43             int d = h[i].node;
    44             q[++ r] = d;
    45         }
    46     }
    47     for (; r; r --)
    48     {
    49         int z = q[r];
    50         F[z] = T[0] = 0, G[z] = Size[z] + C[z];
    51         for (int i = Head[z]; i; i = h[i].next)
    52         {
    53             int d = h[i].node;
    54             F[z] += F[d];
    55             T[++ T[0]] = G[d] - 1;
    56         }
    57         sort(T + 1, T + T[0] + 1);
    58         for (int i = 1; i <= T[0]; i ++)
    59         {
    60             if (G[z] + T[i] <= m)
    61                 G[z] += T[i], F[z] ++;
    62             else break ;
    63         }
    64     }
    65 }
    66  
    67 int main()
    68 {
    69     #ifndef ONLINE_JUDGE
    70         freopen("4027.in", "r", stdin);
    71         freopen("4027.out", "w", stdout);
    72     #endif
    73      
    74     n = getint(), m = getint();
    75     for (int i = 0; i < n; i ++)
    76         C[i] = getint();
    77     for (int i = 0; i < n; i ++)
    78     {
    79         Size[i] = getint();
    80         for (int j = 1; j <= Size[i]; j ++)
    81         {
    82             int d = getint();
    83             addedge(i, d);
    84         }
    85     }
    86     Solve();
    87     printf("%d
    ", F[0]);
    88      
    89     #ifndef ONLINE_JUDGE
    90         fclose(stdin);
    91         fclose(stdout);
    92     #endif
    93     return 0;
    94 }
    4027_Gromah
  • 相关阅读:
    Sql Server常见错误
    sql server复制需要有实际的服务器名称才能连接到服务器
    学习WCF必备网址
    利用Httphandler、UserControl 输出HTML片段
    SQL点滴—性能分析之执行计划
    我的WCF开发框架简化版及基于NET.TCP传输方式的实现
    数据库优化建议
    实现jQuery扩展总结
    【模板】zkw线段树
    洛谷 P1960 列队
  • 原文地址:https://www.cnblogs.com/gromah/p/4471752.html
Copyright © 2011-2022 走看看