题解:AT_abc207_f [ABC207F] Tree Patrolling
显然树上背包,但是每个点的贡献至多为
定义
设
- 若
u 未被染色且未被控制,则v 不能染色:
- 若
u 被控制但不染色,要么u 原来没被控制,被v 染色后控制,要么u 原来就被控制,v 任意。
- 若
u 染色,v 要么已被控制,要么没被控制,此时被u 控制。
初始化:
显然对于每个点
若染本身,
注意一些细节:
-
枚举
i,j 时要倒序枚举,否则会重算。 -
计算前要将
dp_u 复制到t 中,然后dp_u 使用t 转移,否则会重算。 -
-
-
记得取模。
主要代码
void dfs(int u, int fa){
sz[u] = 1;
dp[u][0][0] = 1, dp[u][1][2] = 1;
for(int v : e[u]){
if(v == fa) continue;
dfs(v, u);
for(int i = 0; i <= sz[u] + sz[v]; i ++)
t[i][0] = t[i][1] = t[i][2] = 0;
for(int i = sz[u]; i >= 0; i --)
for(int j = sz[v]; j >= 0; j --){
t[i + j][0] = (t[i + j][0] + dp[u][i][0] * (dp[v][j][0] + dp[v][j][1])) % MOD;
if(i > 0) t[i + j][1] = (t[i + j][1] + dp[u][i - 1][0] * dp[v][j][2] % MOD + dp[u][i][1] * (dp[v][j][0] + dp[v][j][1] + dp[v][j][2]) % MOD) % MOD;
if(i > 0) t[i + j][2] = (t[i + j][2] + dp[u][i][2] * ((j > 0 ? dp[v][j - 1][0] : 0) + dp[v][j][1] + dp[v][j][2])) % MOD;
}
for(int i = 0; i <= sz[u] + sz[v]; i ++)
dp[u][i][0] = t[i][0], dp[u][i][1] = t[i][1], dp[u][i][2] = t[i][2];
sz[u] += sz[v];
}
}