zoukankan      html  css  js  c++  java
  • #树形dp#B 预算缩减

    题目

    给定一棵树,你需要删去一些边(可以不删),使得剩下的图中每个点所在的连通块大小都(geq k)
    求删边的方案数,对(786433)取模。两种方案不同,当且仅当存在一条边在一个方案中被删去,而在另外一个方案中没有被删去。


    分析

    (dp[x][k])表示以点(x)为根的子树中(x)所在的连通块大小为(k)的方案数
    状态转移方程显然,每次都要计算断了一条边的贡献,当且仅当子节点所在的连通块大小不小于(k)
    但是这样(O(n^3))会T掉,考虑当中有很多冗余状态,那么记录子树大小,按照子树大小拼接,时间复杂度(O(n^2))


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N = 5011, mod = 786433;
    struct node {
        int y, next;
    } e[N << 1];
    int dp[N][N], son[N], f[N], ans, as[N], n, k = 1, m;
    inline signed iut() {
        rr int ans = 0;
        rr char c = getchar();
        while (!isdigit(c)) c = getchar();
        while (isdigit(c)) ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar();
        return ans;
    }
    inline signed mo(int x, int y) { return x + y >= mod ? x + y - mod : x + y; }
    inline void dfs(int x, int fa) {
        dp[x][1] = son[x] = 1;
        for (rr int i = as[x], s; i; i = e[i].next)
            if (e[i].y != fa) {
                dfs(e[i].y, x), son[x] += son[e[i].y], s = 0;
                for (rr int j = 1; j <= son[x]; ++j) f[j] = 0;
                for (rr int j = 1; j <= son[x] - son[e[i].y]; ++j)
                    for (rr int o = 1; o <= son[e[i].y]; ++o)
                        f[j + o] = mo(f[j + o], 1ll * dp[x][j] * dp[e[i].y][o] % mod);
                for (rr int o = m; o <= son[e[i].y]; ++o) s += dp[e[i].y][o];
                for (rr int j = 1; j <= son[x]; ++j) dp[x][j] = mo(1ll * dp[x][j] * s % mod, f[j]);
            }
    }
    signed main() {
        freopen("cut.in", "r", stdin);
        freopen("cut.out", "w", stdout);
        n = iut();
        m = iut();
        for (rr int i = 1; i < n; ++i) {
            rr int x = iut(), y = iut();
            e[++k] = (node){ y, as[x] }, as[x] = k;
            e[++k] = (node){ x, as[y] }, as[y] = k;
        }
        dfs(1, 0);
        for (rr int i = m; i <= son[1]; ++i) ans = mo(ans, dp[1][i]);
        return !printf("%d", ans);
    }
    
  • 相关阅读:
    ORA-06530: 引用未初始化的组合 ;
    oracle 简单的sysTimeStamp类型转date 类型
    Luogu P3388 【模板】割点(割顶)
    Luogu P2048 [NOI2010]超级钢琴
    Luogu P2657 [SCOI2009]windy数
    QZEZ第一届“饭吉圆”杯程序设计竞赛
    Luogu P2286 [HNOI2004]宠物收养场
    在平衡树的海洋中畅游(一)——Treap
    Luogu P1129 [ZJOI2007]矩阵游戏
    LOJ #559. 「LibreOJ Round #9」ZQC 的迷宫
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13809575.html
Copyright © 2011-2022 走看看