zoukankan      html  css  js  c++  java
  • [HEOI2013]SAO

    可以发现题目给的是一颗有向树的形式,不论是有向树还是无向树,我们考虑 (dp) 转移基本是从子树转移到当前的父亲,状态也一般涉及的是在子树内部的状态,本题也不例外。

    我们钦定 (1) 为有向树的根,首先可以发现限制每个点位置的那些点一定是这个点在有向树上的儿子或者是父亲,并且只要确定限制它点的位置之后我们就能知道它能放的位置,因此我们就可以考虑令 (dp_{i, j}) 表示在以 (i) 为根的满足子树要求的序列(下面简称子树序列)中 (i) 的位置在 (j) 的方案数。对于 (u ightarrow v) 的边 (v)(u) 在有向树上的儿子,转移的化我们可以考虑枚举 (v) 所在其子树序列的位置 (k),以及 (k) 后面有 (l) 个位置插入到 (j) 之前,那么就有转移:

    [dp_{u, j + k} = dp_{u, j} imes sumlimits_{k = 1} ^ {s_v} dp_{v, k} sumlimits_{l = k} ^ {s_v} dbinom{l + j - 1}{j - 1} imes dbinom{s_v - l + s_u - j}{s_u - j} ]

    其中 (s_i) 表示以 (i) 为根的子树大小。上面的那个 (dp) 后面那一坨计算的东西貌似和 (k) 是没有关系的,可以考虑先枚举 (l) 试试:

    [dp_{u, j + k} = dp_{u, j} imes sumlimits_{k = 1} ^ {s_v} dbinom{k + j - 1}{j - 1} imes dbinom{s_v - k + s_u - j}{s_u - j} imes sumlimits_{l = 1} ^ k dp_{v, l} ]

    后面那一坨显然可以使用前缀和优化掉,这个 (dp) 的复杂度其实是 (O(n ^ 2)) 的,在 [HAOI2015]树上染色 提到了证明方法。

    同理我们可以得到 (v ightarrow u),其中 (v)(u) 的儿子的转移方程:

    [dp_{u, j + k} = dp_{u, j} imes sumlimits_{k = 0} ^ {s_v - 1} dbinom{k + j - 1}{j - 1} imes dbinom{s_v - k + s_u - j}{s_u - j} imes sumlimits_{l = k + 1} ^ {s_v} dp_{v, l} ]

    一样的记录前缀优化可以做到 (O(n ^ 2))

    一些坑点:

    • 以后树形背包直接使用滚动数组记录这一位和上一位的答案这样就不用纠结枚举顺序了。
    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000 + 5
    #define Mod 1000000007
    #define rep(i, l, r) for(int i = l; i <= r; ++i)
    #define dep(i, l, r) for(int i = r; i >= l; --i)
    #define Next(i, u) for(int i = h[u]; i; i = e[i].next)
    struct edge{
        int v, next, w;
    }e[N << 1];
    char opt[N];
    int T, n, u, v, tot, h[N], s[N], dp[2][N][N], C[N][N], S[N][N];
    int read(){
        char c; int x = 0, f = 1;
        c = getchar();
        while(c > '9' || c < '0'){ if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    void add(int u, int v, int w){
        e[++tot].v = v, e[tot].w = w, e[tot].next = h[u], h[u] = tot;
    }
    int Inc(int a, int b){
        return (a += b) >= Mod ? a - Mod : a;
    }
    int Dec(int a, int b){
        return (a -= b) < 0 ? a + Mod : a;
    }
    int Mul(int a, int b){
        return 1ll * a * b % Mod;
    }
    void dfs(int u, int fa){
        s[u] = 1, dp[0][u][1] = 1; int p = 1;
        Next(i, u){
            int v = e[i].v; if(v == fa) continue;
            dfs(v, u);
            if(!e[i].w){
                rep(j, 1, s[u]) rep(k, 1, s[v]){
                    int tmp = Mul(C[k + j - 1][j - 1], C[s[v] - k + s[u] - j][s[u] - j]);
                    dp[p][u][j + k] = Inc(dp[p][u][j + k], Mul(tmp, Mul(dp[p ^ 1][u][j], S[v][k])));
                }
            }
            else{
                rep(j, 1, s[u]) rep(k, 0, s[v] - 1){
                    int tmp = Mul(C[k + j - 1][j - 1], C[s[v] - k + s[u] - j][s[u] - j]);
                    dp[p][u][j + k] = Inc(dp[p][u][j + k], Mul(tmp, Mul(dp[p ^ 1][u][j], Dec(S[v][s[v]], S[v][k]))));
                }
            }
            p ^= 1;
            rep(j, 1, s[u]) dp[p][u][j] = 0;
            s[u] += s[v];
        }
        rep(i, 1, s[u]) S[u][i] = Inc(S[u][i - 1], dp[p ^ 1][u][i]);
    }
    int main(){
        T = read();
        rep(i, 0, N - 5) C[i][0] = 1;
        rep(i, 1, N - 5) rep(j, 1, i) C[i][j] = Inc(C[i - 1][j - 1], C[i - 1][j]);
        while(T--){
            n = read(), tot = 0;
            memset(h, 0, sizeof(h)), memset(dp, 0, sizeof(dp));
            rep(i, 1, n - 1){
                u = read() + 1, scanf("%s", opt + 1), v = read() + 1;
                if(opt[1] == '>') add(u, v, 0), add(v, u, 1);
                else add(u, v, 1), add(v, u, 0);
            }
            dfs(1, 0);
            printf("%d
    ", S[1][n]);
        }
        return 0;
    }
    
    GO!
  • 相关阅读:
    windows下的文件遍历(使用CFindFile)
    hdu 1728 搜索求最少的转向次数
    linux中vsftpd配置文件详解
    QLineEdit 自动完成(使用setCompleter,内含一个ListView)
    Qt 的内部进程通信机制
    qt 获取windows 的消息(通过MFC的DLL的透明窗体转发消息)good
    JS的类型比较与转换图
    使用C#开发ActiveX控件
    MapXtreme+Asp.net 动态轨迹
    MS SQL 日常维护管理常用脚本(二)
  • 原文地址:https://www.cnblogs.com/Go7338395/p/13486189.html
Copyright © 2011-2022 走看看