传送门:
题意
给
一
棵
树
,
有
m
种
颜
色
1
−
m
,
其
中
x
种
是
特
殊
颜
色
,
k
是
特
殊
颜
色
的
编
号
。
给一棵树,有m种颜色1-m,其中x种是特殊颜色,k是特殊颜色的编号。
给一棵树,有m种颜色1−m,其中x种是特殊颜色,k是特殊颜色的编号。
问
如
何
给
树
涂
色
,
特
殊
颜
色
的
节
点
不
能
连
特
殊
颜
色
,
只
能
连
比
他
编
号
小
的
颜
色
。
问如何给树涂色,特殊颜色的节点不能连特殊颜色,只能连比他编号小的颜色。
问如何给树涂色,特殊颜色的节点不能连特殊颜色,只能连比他编号小的颜色。
问 , 能 有 多 少 种 涂 色 方 案 ? 问,能有多少种涂色方案? 问,能有多少种涂色方案?
思路
树 、 节 点 、 计 数 、 特 殊 情 况 − − 树 形 d p 。 树、节点、计数、特殊情况--树形dp。 树、节点、计数、特殊情况−−树形dp。
颜 色 数 量 高 达 1 e 9 , 而 特 殊 颜 色 数 量 只 有 10 , 所 以 我 们 围 绕 特 殊 颜 色 展 开 状 态 转 移 。 颜色数量高达1e9,而特殊颜色数量只有10,所以我们围绕特殊颜色展开状态转移。 颜色数量高达1e9,而特殊颜色数量只有10,所以我们围绕特殊颜色展开状态转移。
因 为 特 殊 颜 色 的 连 接 是 有 要 求 的 , 所 以 可 以 分 成 三 类 。 因为特殊颜色的连接是有要求的,所以可以分成三类。 因为特殊颜色的连接是有要求的,所以可以分成三类。
- 0 表 示 特 殊 颜 色 0表示特殊颜色 0表示特殊颜色
- 1 表 示 比 特 殊 颜 色 编 号 小 的 颜 色 1表示比特殊颜色编号小的颜色 1表示比特殊颜色编号小的颜色
- 2 表 示 比 特 殊 颜 色 编 号 大 的 颜 色 2表示比特殊颜色编号大的颜色 2表示比特殊颜色编号大的颜色
所 以 设 f [ u ] [ i ] [ j ] 表 示 以 u 为 根 节 点 的 子 树 中 , i 个 特 殊 颜 色 , 当 前 点 颜 色 为 j 的 方 案 数 。 所以设f[u][i][j]表示以u为根节点的子树中,i个特殊颜色,当前点颜色为j的方案数。 所以设f[u][i][j]表示以u为根节点的子树中,i个特殊颜色,当前点颜色为j的方案数。
根
据
特
殊
颜
色
来
转
移
:
根据特殊颜色来转移:
根据特殊颜色来转移:
f
[
u
]
[
i
+
j
]
[
0
]
+
=
f
[
u
]
[
i
]
[
0
]
∗
f
[
v
]
[
j
]
[
1
]
f[u][i+j][0]+=f[u][i][0]*f[v][j][1]
f[u][i+j][0]+=f[u][i][0]∗f[v][j][1]
f [ u ] [ i + j ] [ 1 ] + = f [ u ] [ i ] [ 1 ] ∗ ( f [ v ] [ j ] [ 0 ] + f [ v ] [ j ] [ 1 ] + f [ v ] [ j ] [ 2 ] ) f[u][i+j][1]+=f[u][i][1]*(f[v][j][0]+f[v][j][1]+f[v][j][2]) f[u][i+j][1]+=f[u][i][1]∗(f[v][j][0]+f[v][j][1]+f[v][j][2])
f [ u ] [ i + j ] [ 2 ] + = f [ u ] [ i ] [ 2 ] ∗ ( f [ v ] [ j ] [ 1 ] + f [ v ] [ j ] [ 2 ] ) f[u][i+j][2]+=f[u][i][2]*(f[v][j][1]+f[v][j][2]) f[u][i+j][2]+=f[u][i][2]∗(f[v][j][1]+f[v][j][2])
因 为 转 移 的 时 候 是 + = , 所 以 需 要 一 个 辅 助 函 数 来 帮 忙 存 储 , 防 止 新 产 生 的 值 对 后 续 转 移 产 生 影 响 。 因为转移的时候是+=,所以需要一个辅助函数来帮忙存储,防止新产生的值对后续转移产生影响。 因为转移的时候是+=,所以需要一个辅助函数来帮忙存储,防止新产生的值对后续转移产生影响。
Code
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 1e5 + 10;
int n, m, k, x;
vector<int> g[N];
ll dp[11][3], f[N][11][3]; // [以u为根的子树][i种特殊颜色][0/1/2,特殊颜色,小于特殊颜色,大于特殊颜色]
int siz[N];
void dfs(int u, int fa) {
siz[u] = 1;
f[u][1][0] = 1;
f[u][0][1] = k - 1; // 小于特殊颜色的有k-1种
f[u][0][2] = m - k; // 大于特殊颜色的有m-k种
for(auto v : g[u]) {
if(v == fa) continue;
dfs(v, u);
mem(dp, 0);
siz[u] += siz[v];
for(int i = 0;i <= min(siz[u], x); i++) {
for(int j = 0;j <= siz[v] && i + j <= x; j++) {
dp[i + j][0] = (dp[i + j][0] + f[u][i][0] * f[v][j][1] % mod) % mod;
dp[i + j][1] = (dp[i + j][1] + f[u][i][1] * (f[v][j][0] + f[v][j][1] + f[v][j][2]) % mod) % mod;
dp[i + j][2] = (dp[i + j][2] + f[u][i][2] * (f[v][j][1] + f[v][j][2]) % mod) % mod;
}
}
for(int i = 0;i <= min(siz[u], x); i++) {
for(int j = 0;j < 3; j++) {
f[u][i][j] = dp[i][j];
}
}
}
}
void solve() {
scanf("%d%d",&n,&m);
for(int i = 1;i < n; i++) {
int u, v; scanf("%d%d",&u,&v);
g[u].eb(v); g[v].eb(u);
}
scanf("%d%d",&k,&x);
dfs(1, 0);
ll ans = 0;
for(int i = 0;i <= x; i++) {
for(int j = 0;j < 3; j++) {
ans = (ans + f[1][i][j]) % mod;
}
}
printf("%lld\n",ans);
}
signed main() {
solve();
}