https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1903
题目大意:找出所有的深度大于
k
k
k的叶子节点,在每个服务器可以作用
k
k
k距离的情况下,问最少放置多少个服务器能使得这些叶子节点都可以被服务器覆盖。
思路:
n
n
n才
1000
1000
1000的范围,随便写都能过。直接暴力把深度
>
k
>k
>k的叶子节点存下来,然后从后向前遍历,对于每一个未被覆盖的叶子节点,找到其
k
k
k级祖先作为新服务器,然后再以祖先为根给节点打标记就行了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int t,n,s,k;
int fa[1005];
bool vis[1005];
vector<int> vec[1005],edge[1005];
void dfs1(int u,int f,int deep)
{
fa[u]=f;
if(deep>k&&edge[u].size()==1)//叶子节点
vec[deep].push_back(u);
for(int i=0;i<edge[u].size();i++)
if(edge[u][i]!=f)
dfs1(edge[u][i],u,deep+1);
}
void dfs2(int u,int f,int deep)
{
vis[u]=1;
for(int i=0;i<edge[u].size();i++)
if(edge[u][i]!=f&&deep<k)
dfs2(edge[u][i],u,deep+1);
}
void solve()
{
int ans=0,tmp,f;
for(int i=n;i>=0;i--)
{
tmp=vec[i].size();
for(int j=0;j<tmp;j++)
{
if(vis[vec[i][j]])
continue;
++ans;
f=vec[i][j];
for(int x=0;x<k;x++)
f=fa[f];
dfs2(f,f,0);
}
}
printf("%d\n",ans);
}
int main()
{
scanf("%d",&t);
while(t--)
{
for(int i=0;i<1000;i++)
{
vec[i].clear();
edge[i].clear();
}
memset(vis,0,sizeof(vis));
scanf("%d%d%d",&n,&s,&k);
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
edge[u].push_back(v);
edge[v].push_back(u);
}
dfs1(s,s,0);
solve();
}
return 0;
}