思路:
设f[x][i][0,1,2]表示x的子树,覆盖i个,0表示儿子和自己都没选,1表示选自己,2表示选儿子。
那么直接转移。
c o d e code code
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const ll MAXN = 2e3 + 10, mod = 1e9 + 7;
ll n, f[MAXN][MAXN][3], tmp[MAXN][3], size[MAXN];
ll tot, head[MAXN];
struct node {
ll to, next;
}b[MAXN * 2];
void add(ll x, ll y) {
b[++ tot] = (node) { y, head[x] };
head[x] = tot;
}
void dfs(ll x, ll fa) {
size[x] = 1;
f[x][0][0] = f[x][1][1] = 1;
for(ll i = head[x]; i; i = b[i].next) {
ll y = b[i].to;
if(y == fa) continue;
dfs(y, x);
for(ll i1 = size[x]; i1 >= 0; i1 --)
for(ll j1 = size[y]; j1 >= 0; j1 --)
for(ll z1 = 0; z1 <= 2; z1 ++)
for(ll z2 = 0; z2 <= 2; z2 ++) {
ll j = i1 + j1, z = z1;
if(z1 == 0 && z2 == 1) z = 2, j ++;
if(z1 == 1 && z2 == 0) j ++;
tmp[j][z] = (tmp[j][z] + f[x][i1][z1] * f[y][j1][z2] % mod) % mod;
}
size[x] += size[y];
for(ll j = 0; j <= size[x]; j ++)
for(ll z = 0; z <= 2; z ++) {
f[x][j][z] = tmp[j][z];
tmp[j][z] = 0;
}
}
}
int main() {
freopen("cover.in","r", stdin);
freopen("cover.out","w", stdout);
scanf("%lld", &n);
for(ll i = 1; i < n; i ++) {
ll x, y;
scanf("%lld%lld", &x, &y);
add(x, y), add(y, x);
}
dfs(1, 0);
for(ll i = 0; i <= n; i ++) printf("%lld\n", (f[1][i][0] + f[1][i][1] + f[1][i][2]) % mod);
return 0;
}