1. 程式人生 > >noip模擬賽 將軍令

noip模擬賽 將軍令

控制 () code con 推薦 str return 多個 com

技術分享

技術分享

技術分享

分析:對於前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; }

noip模擬賽 將軍令