题目大意:给你一个地图(树),共有1~n个驿站(点),编号分别为1~n,告诉你第ui个驿站与第vi个驿站有一条长度为1的路(边),每个小队(可以放在任意驿站上)最多有k的覆盖长度,问最多要放置多少个小队才能把整张图全部覆盖?
把一个驿站当作市中心(树根),显然离市中心越偏远(深度越深)的驿站就越难被控制,所以我们优先考虑深度最深的节点。用来控制深度最深的节点v的小队应当布置在能控制到v且离v最远的节点u上,这样顺带着控制到的节点是最多的。所以具体操作为:将节点按照深度从大到小排序,判断是否覆盖过,如果没覆盖过,找其k级父亲并覆盖其周围距离不超过k的所有节点。这种方法没有后效性,因为选了一个节点不会导致其它节点不能选。
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <cstdarg> using namespace std; const int MAX_NODE = 100010; int K; void _printf(const char *format, ...) { #ifdef _DEBUG //va_list(args); //va_start(args, format); //vprintf(format, args); //va_end(args); #endif } struct Node { int Id; int Depth; Node *Fa; vector<Node*> Next; bool Ctrled; }_nodes[MAX_NODE], *Root, *Order[MAX_NODE]; int TotNode; void AddEdge(int uId, int vId) { Node *u = _nodes + uId, *v = _nodes + vId; u->Id = uId, v->Id = vId; u->Next.push_back(v); v->Next.push_back(u); } void Read() { int t, u, v; scanf("%d%d%d", &TotNode, &K, &t); for (int i = 1; i <= TotNode - 1; i++) { scanf("%d%d", &u, &v); AddEdge(u, v); } } void Init_Dfs(Node *cur, Node *fa, int depth) { cur->Depth = depth; cur->Fa = fa; _printf("%d->%d depth %d ", fa?fa->Id:0, cur->Id, cur->Depth); int len = cur->Next.size(); for (int i = 0; i < len; i++) if (cur->Next[i] != fa) Init_Dfs(cur->Next[i], cur, depth + 1); } void SetDepth() { Root = _nodes + 1; Init_Dfs(Root, NULL, 1); } bool Cmp_Depth(Node *a, Node *b) { return a->Depth > b->Depth; } void SetOrder() { for (int i = 1; i <= TotNode; i++) Order[i] = _nodes + i; sort(Order + 1, Order + TotNode + 1, Cmp_Depth); } void SetCtrl_Dfs(Node *fa, Node *cur, int k) { _printf("ctrled %d ", cur->Id); cur->Ctrled = true; int len = cur->Next.size(); if (k < K) for (int i = 0; i < len; i++) if (cur->Next[i] != fa) SetCtrl_Dfs(cur, cur->Next[i], k + 1); } int SetCtrl() { int ans = 0; for (int i = 1; i <= TotNode; i++) { Node *cur = Order[i]; if (!cur->Ctrled) { _printf("deepest %d ", cur->Id); ans++; for (int j = 1; j <= K && cur->Fa; j++) cur = cur->Fa; _printf("lighted %d ", cur->Id); SetCtrl_Dfs(NULL, cur, 0); } } return ans; } int main() { Read(); SetDepth(); SetOrder(); printf("%d ", SetCtrl()); return 0; }