题意:
n台机器连成一个树状网络,其中叶节点是客户端,其他结点是服务器。目前有一台服务器正在提供VOD服务,虽然视频本身质量不错,但对于那些离它很远的客户端来说,网络延迟却难以忍受。你的任务是在一些其他服务器上也安装同样的服务,使得每台客户端到最近服务器的距离不超过一个给定的整数k。为了节约成本,安装服务的服务器台数应尽量少。
思路:
第一次遍历这个树,将距离VOD超过k的叶结点存入变长数组,同时更进father数组,保存每个结点的父结点
然后找到变长数组中未标记的叶结点的k级祖先(显然这样是最优的)
第二次遍历这个树,将找到的k级祖先以及因此能覆盖到的范围全标记
代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
vector<int> edge[1005], g[1005];
int father[1005], cover[1005];
int k, s, n;
void init() {
int u, v;
for(int i=0; i<=n; i++) {
edge[i].clear();
g[i].clear();
}
memset(father, 0, sizeof(father));
memset(cover, 0, sizeof(cover));
for(int i=1; i<n; i++) {
scanf("%d%d", &u, &v);
edge[u].push_back(v);
edge[v].push_back(u);
}
}
void dfs(int v, int pre, int d) {
father[v] = pre;
if(edge[v].size()==1 && d>k) g[d].push_back(v);
for(int i=0; i<edge[v].size(); i++) {
int u = edge[v][i];
if(u == pre) continue;
dfs(u, v, d+1);
}
}
void dfs2(int v, int pre, int d) {
cover[v] = 1;
for(int i=0; i<edge[v].size(); i++) {
int u = edge[v][i];
if(u == pre) continue;
if(d<k) {
dfs2(u, v, d+1);
}
}
}
void deal() {
dfs(s, -1, 0); //排除与VOD相距小于k的点
int v, u;
int ans = 0;
for(int i=n-1; i>k; i--) {
for(int j=0; j<g[i].size(); j++) {
u = g[i][j];
if(cover[u]) continue;//找到最远未覆盖的点
v = u;
for(int j=0; j<k; j++) v = father[v];
dfs2(v, -1, 0);
ans++;
}
}
printf("%d\n", ans);
}
int main() {
int kase;
scanf("%d", &kase);
while(kase--) {
scanf("%d%d%d", &n, &s, &k);
init();
deal();
}
return 0;
}