[USACO 2017 December Gold] Barn Painting
题目大意:
给定一颗 \(N\) 个节点组成的树,\(\texttt{3}\) 种颜色,其中 \(K\) 个节点已染色,要求任意两相邻节点颜色不同,求合法染色方案数。
正文:
考虑用树形DP,设 \(f_{x,i}\) 表示节点 \(x\) 为根的子树且它涂了颜色 \(i\) 的的染色方案。那么动态转移方程就显而易见了:
\[\begin{aligned}f_{x,0}& =(f_{y,1}+f_{y,2})f_{x,0}\quad(y\in\text{son}(x))\\f_{x,1}& =(f_{y,0}+f_{y,2})f_{x,1}\quad(y\in\text{son}(x))\\f_{x,2}& =(f_{y,0}+f_{y,1})f_{x,2}\quad(y\in\text{son}(x))\end{aligned}
\]
代码:
void dfs(int x, int fa)
{
for (int y = 0; y < 3; y++)
{
if(f[x][y] == 1)
{
for (int y1 = 0; y1 < y; y1++)
f[x][y1] = 0;
break;
}
f[x][y] = 1;
}
for (int i = head[x]; i; i = e[i].next)
{
int v = e[i].to;
if(v != fa)
{
dfs(v, x);
f[x][0] = f[x][0] * ((f[v][1] + f[v][2]) % mod) % mod;
f[x][1] = f[x][1] * ((f[v][0] + f[v][2]) % mod) % mod;
f[x][2] = f[x][2] * ((f[v][0] + f[v][1]) % mod) % mod;
}
}
}