P3942 将军令
Departure_ · · 题解
P3942 将军令
若一个点被选择,则它能覆盖到与其距离小于等于
注意到
考虑初始化,显然有
考虑转移,设
当
当
先考虑包含点
我们设
- 若点
v 只能被其子树内的点控制,则可以随便选,即mn_v=\min\limits_{k=0}^{K} \{f_{v,k}\} 。 - 当且仅当
dis_{v,t}=dis_{u,t}+1\le K ,点v 还能被刚才我们选出的点t 控制,于是有mn_v=\min\{\min\limits_{k=0}^{K} \{f_{v,k}\},f_{v,K+j+1}\} 。
于是我们得到
为了方便取到最优的点
当
类似地,我们设
- 若点
v 只能被其子树内的点控制,则可以随便选,即mn_v=\min\limits_{k=0}^{K} \{f_{v,k}\} 。 - 当且仅当
dis_{v,t}=dis_{u,t}+1\le K ,点v 还能被点t 控制,于是有mn_v=\min\{\min\limits_{k=0}^{K} \{f_{v,k}\},f_{v,j+1}\} 。
于是有
至此我们得到了全部的转移。
最后考虑统计答案,我们令
复杂度
int f[Maxn][Maxk * 2];
void dfs(int u, int lst) {
f[u][0] = 1;
for (int j = 1; j <= K; ++j) f[u][j] = INF;
for (int j = K + 1; j <= 2 * K; ++j) f[u][j] = 0;
for (int i = head[u]; i; i = eg[i].pre) {
int v = eg[i].to;
if (v == lst) continue;
dfs(v, u);
int mn = INF;
for (int k = 0; k <= 2 * K; ++k) mn = min(mn, f[v][k]);
f[u][0] += mn;
}
for (int j = 1; j <= K; ++j) {
static int mn[Maxn];
int sum = 0;
for (int i = head[u]; i; i = eg[i].pre) {
int v = eg[i].to;
if (v == lst) continue;
mn[v] = INF;
for (int k = 0; k <= K; ++k) mn[v] = min(mn[v], f[v][k]);
if (K + j + 1 <= 2 * K) mn[v] = min(mn[v], f[v][K + j + 1]);
sum += mn[v];
}
for (int i = head[u]; i; i = eg[i].pre) {
int v = eg[i].to;
if (v == lst) continue;
f[u][j] = min(f[u][j], sum - mn[v] + f[v][j - 1]);
}
}
for (int j = K + 1; j <= 2 * K; ++j) {
for (int i = head[u]; i; i = eg[i].pre) {
int v = eg[i].to;
if (v == lst) continue;
int mn = INF;
for (int k = 0; k <= K; ++k) mn = min(mn, f[v][k]);
if (j + 1 <= 2 * K) mn = min(mn, f[v][j + 1]);
f[u][j] += mn;
}
}
}
// for (int j = 0; j <= K; ++j) ans = min(ans, f[1][j]);