cf855 C. Helga Hufflepuff's Cup
题意:
在给定的一棵树上给节点染色。可以染m种颜色。定义一种特殊颜色mx,一棵树上最多能有mc个mx;如果一个节点为mx,那么他相邻的节点的值只能选比他小的颜色。问染色方案数。
\(n\le 1e5, 1\le m\le 1e9, 1\le mc \le 10\)
思路:
\(f(u,0/1/2,i)\) 表示 \(u\) 节点染 \([1,mx]/mx/[mx+1,m]\) ,以 \(u\) 为根的树中有 \(i\) 个 \(mx\) 的方案数。答案为 \(\Sigma f(1,0\sim 2,0\sim mc)\)
每次树形dp都要解决这样一个问题:有 \(soncnt+1\) 堆石子,已知在每堆石子中选 \(0,1,2,\cdots mc\) 个的方案数,求一共选 \(0,1,2,\cdots mc\) 个的方案数。
这(大概)是个背包问题,枚举之前已经选的个数 \(i\),现在要从新的堆中选的个数 \(j\) 进行转移。要开个备份数组。
ll n, m, mx, mc, f[N][3][11], g[3][11];
void dfs(int u, int fa) {
f[u][0][0] = mx - 1, f[u][1][1] = 1, f[u][2][0] = m - mx;
for(int v : G[u]) if(v != fa) {
dfs(v, u);
memset(g, 0, sizeof g);
for(int i = 0; i <= mc; i++)
for(int j = 0; i + j <= mc; j++)
add(g[0][i+j], f[u][0][i] * (f[v][0][j] + f[v][1][j] + f[v][2][j])),
add(g[1][i+j], f[u][1][i] * f[v][0][j]),
add(g[2][i+j], f[u][2][i] * (f[v][0][j] + f[v][2][j]));
memcpy(f[u], g, sizeof g);
}
}
signed main() {
iofast;
cin >> n >> m;
for(int i = 1, a, b; i < n; i++)
cin >> a >> b, G[a].pb(b), G[b].pb(a);
cin >> mx >> mc;
dfs(1, 0);
int ans = 0;
for(int i = 0; i < 3; i++)
for(int j = 0; j <= mc; j++)
(ans += f[1][i][j]) %= mod;
cout << ans;
}

浙公网安备 33010602011771号