潜入行动 为例, 主要是dfs部分的代码,每次合成两个树,然后再把新的树往上面和,转移会非常容易
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e5 + 10, mod = 1e9 + 7;
int f[N][105][2][2], n, k, siz[N], g[105][2][2];
vector<int>E[N];
int add(int x, int y) { return (x + y) % mod; }
int mul(int x, int y) { return (1ll * x * y %mod);}
void dfs(int fa, int u) {
//初始化区
siz[u] = 1;
f[u][0][0][0] = f[u][1][1][0] = 1;
//遍历区
for (int v : E[u]) {
if (v == fa) continue;
dfs(u, v);
//转移区
for (int i = 0; i <= min(k, siz[u]); i++) {
for (int j = 0; j <= min(k, siz[v]) && j + i <= k; j++) {
g[i + j][0][0] = add(g[i + j][0][0], mul(f[u][i][0][0], f[v][j][0][1]));
g[i + j][1][0] = add(g[i + j][1][0], mul(f[u][i][1][0], add(f[v][j][0][0], f[v][j][0][1])));
g[i + j][0][1] = add(g[i + j][0][1], add(mul(f[u][i][0][1], add(f[v][j][0][1], f[v][j][1][1])), mul(f[u][i][0][0], f[v][j][1][1])));
g[i + j][1][1] = add(g[i + j][1][1], add(mul(f[u][i][1][0], add(f[v][j][1][0], f[v][j][1][1])),
mul(f[u][i][1][1], add(f[v][j][0][0], add(f[v][j][1][0], add(f[v][j][1][1], f[v][j][0][1]))))));
}
}
siz[u] += siz[v];
//覆盖清空区
for (int i = 0; i <= min(k, siz[u]); i++) {
f[u][i][0][0] = g[i][0][0]; g[i][0][0] = 0;
f[u][i][0][1] = g[i][0][1]; g[i][0][1] = 0;
f[u][i][1][0] = g[i][1][0]; g[i][1][0] = 0;
f[u][i][1][1] = g[i][1][1]; g[i][1][1] = 0;
}
// for (int i = 0; i <= k; i++) g[i][0][0] = g[i][0][1] = g[i][1][0] = g[i][1][1] = 0;
}
}
signed main() {
cin >> n >> k;
for (int i = 1; i < n; i++) {
int u, v; cin >> u >> v;
E[u].push_back(v); E[v].push_back(u);
}
dfs(0, 1);
// cout << f[3][2][1][1] <<' ' << f[3][2][0][1] << ' ' << f[3][2][1][0]<< endl;
cout << add(f[1][k][1][1], f[1][k][0][1]) << endl;
}
标签:return,int,back,dfs,树形,long,格式,dp,mod
From: https://www.cnblogs.com/lyrrr/p/18583934