题目链接:https://cn.vjudge.net/problem/16451/origin
题意:一个服务器能覆盖k距离的用户点,每个叶子节点都是用户点,初始位置s有一个服务器。数据是一颗树。问最少要多少个点当服务器能覆盖全部用户。
输入:T组数据,n个节点,s,k,n-1行表示边。
思路:把已给的服务器点当根,每次从最远未覆盖的叶子节点开始,第k个父亲节点当服务器的点。
#include<vector>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#define M 1010
using namespace std;
int fa[M];
int t,n,r,k,F[M],book[M];
vector<int>node[M];
vector<int>A[M];
void dfs(int u,int v,int tep)
{
fa[u]=v;
int len=A[u].size();
if(len==1&&tep>k) node[tep].push_back(u);
for(int i=0; i<len; i++)
{
if(A[u][i]==v) continue;
dfs(A[u][i],u,tep+1);
}
return ;
}
int bfs(int u,int tep)
{
if(tep>k) return 0;
if(F[u]) return 1;
return bfs(fa[u],tep+1);
}
void pan(int u,int v,int tep)
{
int len=A[u].size();
if(tep>k) return ;
if(A[u].size()==1) book[u]=1;
for(int i=0; i<len; i++)
{
if(A[u][i]==v) continue;
pan(A[u][i],u,tep+1);
}
return ;
}
int solve()
{
int ans=0;
memset(F,0,sizeof(F));
memset(book,0,sizeof(book));
F[r]=1;
for(int i=1; i<=n; i++) node[i].clear();
dfs(r,0,1);
for(int i=n; i>=k; i--)
{
if(node[i].size())
{
for(int j=0; j<node[i].size(); j++)
{
if(!bfs(node[i][j],0)&&!book[node[i][j]])
{
int li=node[i][j];
for(int v=1; v<=k; v++)
{
li=fa[li];
}
F[li]=1;
pan(li,0,0);
ans++;
}
}
}
}
return ans;
}
int main()
{
int x,y;
scanf("%d",&t);
while(t--)
{
for(int i=1; i<=n; i++) A[i].clear();
scanf("%d%d%d",&n,&r,&k);
for(int i=1; i<n; i++)
{
scanf("%d%d",&x,&y);
A[x].push_back(y);
A[y].push_back(x);
}
printf("%d\n",solve());
}
return 0;
}