题目大意:n台机器连成一个树状网络,其中叶节点是客户端,其他节点是服务器。现在有一台服务器在节点s,服务器能传播的信号的距离为k,因为有的用户距离服务器的距离大于k,所以必须添加服务器。问最少要添加几个服务器,才能使每个客户端都收到信号
解题思路:将节点S作为树根,记录每个节点的父节点,并把叶子节点距离根节点的距离记录下来,然后再枚举距离超过k的节点,距离从大到小进行枚举,如果该叶节点没有被覆盖,就找到其距离为k的祖先节点放置服务器,因为这样放置才会使放置服务器的数量达到最小
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define maxn 1010
int N, S, K, fa[maxn];
vector<int> nodes[maxn], gr[maxn];
bool covered[maxn];
void dfs(int u, int f, int d) {
fa[u] = f;
int size = gr[u].size();
if(size == 1 && d > K)
nodes[d].push_back(u);
for(int i = 0; i < size; i++) {
int v = gr[u][i];
if(v != f)
dfs(v,u,d+1);
}
}
void dfs2(int u, int f, int d) {
covered[u] = true;
int size = gr[u].size();
for(int i = 0; i < size; i++) {
int v = gr[u][i];
if(v != f && d < K)
dfs2(v,u,d+1);
}
}
int solve() {
int ans = 0;
memset(covered,0,sizeof(covered));
for(int d = N - 1; d > K; d--) {
for(int i = 0; i < nodes[d].size(); i++) {
int u = nodes[d][i];
if(covered[u])
continue;
int v = u;
for(int j = 0; j < K;j++)
v = fa[v];
dfs2(v,-1,0);
ans++;
}
}
return ans;
}
int main() {
int test;
scanf("%d",&test);
while(test--) {
scanf("%d%d%d",&N,&S,&K);
for(int i = 1; i <= N; i++) {
gr[i].clear();
nodes[i].clear();
}
for(int i = 0; i < N - 1; i++) {
int a, b;
scanf("%d%d",&a,&b);
gr[a].push_back(b);
gr[b].push_back(a);
}
dfs(S,-1,0);
printf("%d\n",solve());
}
return 0;
}