树规+背包

最近做的好题挺多,写下题解;
树规+背包专题:
熟练pou分:
感觉还是学长的方法比较好,直接dp方案数,最后乘概率,简单有效;
树上染色:
一开始dp式想错(以下为错误题解)
{
考虑到每个子树的情况,易想到
f[i][j][0/1]表示以i为根的子树中,(i为黑/白子)j个黑子的最优值;
d[i][j][0/1][0/1]表示对应状态下子树中所有黑/白子到根节点距离;
后来发现这只能满足局部最优而不能满足全局最优。。。
}
所以直接考虑每条边对全局的贡献;
dp式自己yy一下就出来了

可怜与超市;相对简单
注意合并的范围,n^2与n^3只在一念之间;
应该先转移dp值再累加子树大小,否则,
根据点对,在一条链时会被卡到n^3(叶子点对数达到n^2)

最后一题:sao;
题目名就够sao的;而题目更是sao得一pi;
大多数人刚看时会把它看成DAG(有向无环),我就是大多数人。。。
后来发现可以当成树,在转移时考虑方向即可;
f[i][j]表示考虑到以i为根的子树中根节点排名为j的方案数;
记录前缀和转移,中间加一些组合数;
附一个bug极多的半成品;
if(w[i]==1)//
{
    for(int j=sz[g];j>=1;--j)
    {
        if(!tmp[po^1][j])continue;
        for(int k=1;k<=sz[to[i]];++k)
        {                    
            tmp[po][j+k]+=tmp[po^1][j]*(sum[to[i]][sz[to[i]]]-sum[to[i]][k])*C[j+k-1][k] *C[sz[to[i]]+sz[g]-j-k][sz[g]-j];
            tmp[po][j+k]%=mod;
        }
        tmp[po][j]+=tmp[po^1][j]*sum[to[i]][sz[to[i]]] *C[sz[to[i]]+sz[g]-j][sz[g]-j] ;
        tmp[po^1][j]=0;
    }
}

else
{
    for(int j=sz[g];j>=1;--j)
    {
        if(!tmp[po^1][j])continue;
        for(int k=1;k<=sz[to[i]];++k)
        {
            tmp[po][j+k]+=tmp[po^1][j]*sum[to[i]][k] *C[j+k-1][k] *C[sz[to[i]]+sz[g]-j-k][sz[g]-j] ;    
            tmp[po][j+k]%=mod;
        }
        tmp[po^1][j]=0;
    }
}
总结:所谓树规+背包,开局一个点,子树全靠合
(包括非叶子节点)所有点的初始化都相同;
所以,问题就转化为了两个子树的合并问题,
这时我们考虑两个子树的根节点的贡献或花费以及相连的边的贡献或花费,
再套个背包的板子,注意转移时点对数就可以了;

posted @ 2019-07-21 11:50  真-不能AKt♞  阅读(143)  评论(1编辑  收藏  举报