标签: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)); }
标签:fine font str color iostream 树形dp printf 注意 print
原文地址:https://www.cnblogs.com/uid001/p/10279599.html