分析:对于前18个点可以考虑非常恶心的树形dp,不推荐这种方法.其实贪心还是很显然的.每个小队可以控制距离不超过k里的驿站,肯定要让这个k里不能白白浪费.对于所有叶子节点,如果它还没有被控制,那么肯定要在它的第k级祖先派一个小队.这样能保证控制到它,还能控制到尽可能多的点.这样,将所有点按照深度排序,从深度最深的点里面找没有被控制到的,找到它的第k级祖先,然后dfs暴力覆盖.
Qusetion:为什么不从深度最浅的点找?
每个子节点只有一个祖先,而每个祖先可能会有多个子节点,不知道在哪里派小队最优.
莫名被卡掉了一个点:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 200010; int n, k, t, head[maxn], to[maxn], nextt[maxn], tot = 1, dep[maxn], sum, vis[maxn], ans; struct node { int id, x; }e[maxn]; void add(int x, int y) { to[tot] = y; nextt[tot] = head[x]; head[x] = tot++; } void dfs(int u, int fa, int dist) { dep[u] = dist; for (int i = head[u]; i; i = nextt[i]) { int v = to[i]; if (v == fa) continue; dfs(v, u, dist + 1); } } void color(int x, int depth, int p) { if (!vis[x]) sum++; vis[x] = 1; if (depth == p) return; for (int i = head[x]; i; i = nextt[i]) color(to[i], depth + 1, p); } bool cmp(node a, node b) { return a.x > b.x; } int main() { scanf("%d%d%d", &n, &k, &t); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); add(u, v); add(v, u); } dfs(1, 0, 1); for (int i = 1; i <= n; i++) e[i].id = i, e[i].x = dep[i]; sort(e + 1, e + 1 + n, cmp); for (int i = 1; i <= n; i++) if (!vis[e[i].id]) { ans++; int u = e[i].id; for (int j = 1; j <= k; j++) { for (int kk = head[u];kk;kk = nextt[kk]) { int v = to[kk]; if (dep[v] < dep[u]) { u = v; break; } } } color(u, 1, k + 1); } printf("%d\n", ans); return 0; }
时间: 2024-11-03 23:22:40