经典题,需要温习。
题目链接:点击这里
总体思路
- 此题是网络结构,好久没做过这种题了。需要注意的是,这里有n个点,只有n-1条边,一定是无环图。因此,此题是无根树。
- 处理无根树比较麻烦,我们只知道一台server的编号,可以从这个server出发进行DFS,找到在其k距离范围内能达到的叶子节点(client)。但接下来怎么做呢?如何找到剩余叶子节点的最小server数呢?
- 因此,可以将无根树转化为有根数,就把server当作根节点,第一次DFS找到可以到达的所有叶子节点,然后从深度最深的叶子节点出发,找到其k祖先,将其设置为server,很容易证明这样是最省的。
代码实现
- 思路不是很难想,但代码上需要有些技巧。
树的构建
- 我们知道,可以使用邻接矩阵来构建,但在无向图中太浪费空间,并且此题n最大可以去1000,会造成内存溢出。
- 因此我们可以采用邻接链表的形式,由于此题只有编号没有其他信息,因此可构建树
vector<int> nodes[maxn]
; - 如何快速的找到其k个祖先呢?这里使用了一个数组进行存储其父节点,需要注意的是,由于此题是无向图,因此要注意方向,不然会造成死循环。
示例代码
由于深度不超过k的叶子节点已经被服务器覆盖了,因此我们存储深度的时候,只存储深度大于k的节点,使用DFS来覆盖。
#include <iostream> #include <vector> #include <set> #include <string.h> using namespace std; int N; /* numbers of node */ int n, s, k; /* n is the nodes, s is server,k is distance */ const int maxn = 1000 + 10; /* max nodes */ vector<int> nodes[maxn]; vector<int> depth[maxn]; bool covered[maxn]; int fa[maxn]; void get_father(int point, int father, int dis) { fa[point] = father; int num = nodes[point].size(); if (num == 1 && dis > k) /* if point is client and depth >k , store the depth*/ depth[dis].push_back(point); for (int i = 0; i < num; i++) { int child = nodes[point][i]; if (child != father) get_father(child, point, dis + 1); } } /* set server on point */ void dfs(int point, int father, int dis) { covered[point] = true; int num = nodes[point].size(); for (int i = 0; i < num; i++) { int child = nodes[point][i]; /* be careful child != father */ if (child != father && dis < k) dfs(child, point, dis + 1); } } int solve() { int ans = 0; memset(covered, 0, sizeof(covered)); for (int d = n - 1; d > k; d--) { for (int i = 0; i < depth[d].size(); i++) { int point = depth[d][i]; if (covered[point]) continue; int temp = point; /* find dis = k father */ for (int j = 0; j < k; j++) temp = fa[temp]; dfs(temp, -1, 0); ans++; } } return ans; } int main() { int kcase; cin >> kcase; for (int kk = 1; kk <= kcase; kk++) { cin >> n >> s >> k; for (int i = 1; i <= n; i++) { nodes[i].clear(); depth[i].clear(); } for (int i = 1; i < n; i++) { int a, b; cin >> a >> b; nodes[a].push_back(b); nodes[b].push_back(a); } get_father(s, -1, 0); cout << solve() << endl; } return 0; }