题解:P9983 [USACO23DEC] Cowntact Tracing P
令经过了
考虑先预处理出所有可能的初始感染源,即到任意一个
如果存在一个点到最近初始感染源的距离
现在我们只需要在初始感染源集合中选取最少的点恰好覆盖所有为
我们将所有
考虑怎么快速查询这个东西。
我们预处理一个
选定
这里给一下预处理
:::success[code]
vi f(n + 1, 0), seq(n); iota(seq.begin(), seq.end(), 1);
sort(seq.begin(), seq.end(), [](int a, int b){ return dep[a] > dep[b]; });
rep(u, seq){
int s = vis[u] ? u : 0;
rep(v, g[u]) if (v != fa[u]){
int t = f[v];
if (dep[t] < dep[s]) s = t;
}
f[u] = s;
}
// L(i, 1, n) std::cout << f[i] << " \n"[i == n];
vi rem(n + 1, -1); int ans = 0;
rep(u, I){
if (rem[u] >= 0) continue;
int s = 0, x = u;
for (rg int _ = 0; _ <= k && x != 0; _++){
int v = f[x];
if (dep[u] - dep[x] + dep[v] - dep[x] <= k && dep[v] < dep[s]) s = v;
x = fa[x];
}
// std::cout << s << "\n";
ans++, rem[s] = k, q.push(s);
while(q.size()){
int u = q.front(); q.pop(); if (!rem[u]) continue;
rep(v, g[u]) if (rem[v] < rem[u] - 1) rem[v] = rem[u] - 1, q.push(v);
}
}
std::cout << ans << "\n";
:::
考虑分析一下复杂度,首先预处理
首先每一个
假设我们选择了
而一共最多只有
所以
故最坏时间复杂度为