专栏文章
题解:AT_abc207_f [ABC207F] Tree Patrolling
AT_abc207_f题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mio2pnfp
- 此快照首次捕获于
- 2025/12/02 12:23 3 个月前
- 此快照最后确认于
- 2025/12/02 12:23 3 个月前
显然树上背包,但是每个点的贡献至多为 ,若该点被控制则相邻点染色时该点无贡献,故而仅使用 表示 子树中有 个被控制是不够的,需要多添加一些信息。
定义 表示 子树中有 个被控制, 代表 未染色也未被控制, 代表 被控制但没被染色, 表示 染色,不可能出现染色但没被控制的情况,因为染色即控制了本身。
设 为当前节点, 为其中一个儿子,枚举 已遍历子树被控制的个数 和 为根的子树被控制点个数 ,转移方程如下:
- 若 未被染色且未被控制,则 不能染色:
- 若 被控制但不染色,要么 原来没被控制,被 染色后控制,要么 原来就被控制, 任意。
- 若 染色, 要么已被控制,要么没被控制,此时被 控制。
初始化:
显然对于每个点 ,若不染本身,。
若染本身,。
注意一些细节:
-
枚举 时要倒序枚举,否则会重算。
-
计算前要将 复制到 中,然后 使用 转移,否则会重算。
-
和 由于 本身被控制所以在 时才能转移。
-
在转移时 可能为负数,所以 只有 时才能加上 。
-
记得取模。
主要代码
CPPvoid 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];
}
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...