先根据根服务器位置,将五根树转换为有根树,
然后,每次深度最大的未被覆盖到的节点,选其k级祖先做服务器、证明,就是假设法。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cctype>
using namespace std;
typedef long long LL;
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep1(i,n) for(int (i)=1;(i)<=(n);(i)++)
const int maxn = 1110;
vector<int> G[maxn];
int sx,k,n;
struct node{
int id,dep;
bool operator <(const node& a)const{
return dep<a.dep;
}
}a[maxn];
int fat[maxn];
vector<node> ans;
void dfs(int u,int fa,int depth){
a[u].id = u; a[u].dep = depth;
fat[u] = fa;
if(G[u].size()==1&&G[u][0]==fa){
if(depth > k) ans.push_back(a[u]);
return ;
}
for(int i=0;i<G[u].size();i++){
int v = G[u][i];
if(v==fa) continue;
dfs(v,u,depth+1);
}
}
int vis[maxn];
void kuo(int u,int fa,int tk){
vis[u] = 1;
for(int i=0;i<G[u].size();i++){
int v = G[u][i];
if(v == fa) continue;
if(tk<k) kuo(v,u,tk+1);
}
}
int find_fa(int x,int d){
return (d == k ? x:find_fa(fat[x],d+1));
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d %d %d",&n,&sx,&k);
rep1(i,n) G[i].clear();
rep(i,n-1){
int x,y;
scanf("%d %d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
ans.clear();
dfs(sx,-1,0);
memset(vis,0,sizeof(vis));
if(ans.size()>0){
sort(ans.begin(),ans.end());
}
int res = 0;
kuo(sx,-1,0);
if(ans.size()>0)
for(int i=ans.size()-1;i>=0;i--){
int v = ans[i].id;
if(!vis[v]){
kuo(find_fa(v,0),-1,0);
res++;
}
}
printf("%d\n",res);
}
return 0;
}