码迷,mamicode.com
首页 > 其他好文 > 详细

树形dp总结

时间:2019-01-16 22:52:43      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:fine   font   str   color   iostream   树形dp   printf   注意   print   

例1, CF736C

大意:给定树, 可以选一些点涂黑, 求使得所有点到最近的黑点距离不超过k的方案数

 

注意到最近的黑点可能在子树外也可能在子树内, 这里可以分两种情况讨论

假设$f_1[x][i]$为$x$子树的黑点到$x$的最近距离为i的方案
$f_2[x][i]$为$x$子树中还有若干点没有匹配到黑点, 最多能再走$i$步的方案
初始状态$f_1[x][0]=f_2[x][k]=1$

$O(nk^2)$暴力转移即可
需要注意 1.对每个儿子要先转移完,再更新方案
2.新添加的点到当前根距离要+1, 之前更新过的不要多加

 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
typedef long long ll;
const int P = 1e9+7;

int n, k;
ll f1[111][111], f2[111][111], t1[111], t2[111];
vector<int> g[111];

void dfs(int x, int fa) {
    f1[x][0] = f2[x][k] = 1;
    for (int y:g[x]) if (y!=fa) {
        dfs(y,x);
        REP(i,0,k) t1[i]=t2[i]=0;
        REP(i,0,k) REP(j,0,k) {
            ll L1=f1[x][i],R1=f1[y][j],L2=f2[x][i],R2=f2[y][j];
            (t1[min(i,j+1)]+=L1*R1)%=P;
            if (i+1<=j) (t1[i]+=L1*R2)%=P;
            else if (j) (t2[j-1]+=L1*R2)%=P;
            if (j+1<=i) (t1[j+1]+=L2*R1)%=P;
            else (t2[i]+=L2*R1)%=P;
            if (j) (t2[min(i,j-1)]+=L2*R2)%=P;
        }
        REP(i,0,k) f1[x][i]=t1[i],f2[x][i]=t2[i];
    }
}

int main() {
    scanf("%d%d", &n, &k);
    if (!k) return puts("1"),0;
    REP(i,2,n) {
        int u, v;
        scanf("%d%d", &u, &v);
        g[u].push_back(v),g[v].push_back(u);
    }
    dfs(1,0);
    ll ans = 0;
    REP(i,0,k) ans+=f1[1][i];
    printf("%d\n",int(ans%P));
}

 

树形dp总结

标签:fine   font   str   color   iostream   树形dp   printf   注意   print   

原文地址:https://www.cnblogs.com/uid001/p/10279599.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!