简略题意:给出一颗树,有m种颜色,第k种颜色是特殊颜色,树上最多有x个特殊颜色点。
你需要把整个树染色,且保证特殊颜色节点以下条件:
1. 与其相连的不能有特殊颜色节点。
2. 与其相连的节点的颜色序号必须小于k。
问有多少种满足要求的树。
这题的突破点在于x很小。
其实节点的颜色种类只有3种:
0. 能够和特殊颜色相连的点(小于k)。
1. 特殊颜色点(等于k)。
2. 特殊颜色外,不能和特殊颜色相连的点(大于k)。
考虑
dp[u][i][0/1/2]
,表示以
u
为根的子树中,有
枚举当前
u
子树中特殊节点个数
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn = 110000;
LL dp[maxn][12][3];
vector<int> G[maxn];
const int mod = 1e9+7;
namespace treedp{
int n, m;
int k, x;
void dfs(int u, int fa) {
dp[u][0][0] = k - 1, dp[u][1][1] = 1, dp[u][0][2] = m - k;
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(v == fa) continue;
dfs(v, u);
LL buf[12][3] = {0};
for(int j = x; j >= 0; j--) {
for(int k = 0; k <= j; k++) {
buf[j][0] += (dp[v][k][0] + dp[v][k][1] + dp[v][k][2]) * dp[u][j-k][0];
buf[j][0] %= mod;
buf[j][1] += dp[v][k][0] * dp[u][j-k][1];
buf[j][1] %= mod;
buf[j][2] += (dp[v][k][0] + dp[v][k][2]) * dp[u][j-k][2];
buf[j][2] %= mod;
}
}
memcpy(dp[u], buf, sizeof buf);
}
}
void solve() {
scanf("%d%d", &n, &m);
for(int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
scanf("%d%d", &k, &x);
dfs(1, -1);
LL sum = 0;
for(int i = 0; i <= x; i++) {
sum += dp[1][i][0] + dp[1][i][1] + dp[1][i][2];
sum %= mod;
}
printf("%lld\n", sum);
}
}
int main() {
treedp::solve();
return 0;
}