先根据根服务器位置,将五根树转换为有根树,
然后,每次深度最大的未被覆盖到的节点,选其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; }