题目链接:
Network
题目解析:
将原本的无根树,以原始VOD服务器为根,转变为有根树.对于已经满足条件的客户端直接忽略.
将剩余所有叶子节点按深度入队,之后从最深的一层向上遍历.如果发现未被覆盖的叶子节点,就向上回溯k层后插入一个服务器.
每插入一个服务器,就进行一次DFS,覆盖与它相距不超过k的所有叶子节点.
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<cmath>
#include<vector>
using namespace std;
#define ll long long
vector<int>gr[1010],nodes[1010];
int n,s,k,fa[1010],vis[1010];
void dfs(int u,int f,int d)
{
fa[u]=f;
int num=gr[u].size();
if(num==1 && d>k) nodes[d].push_back(u);
for(int i=0;i<num;i++)
{
int v=gr[u][i];
if(v!=f) dfs(v,u,d+1);
}
}
void ddfs(int u,int f,int d)
{
vis[u]=1;
int num=gr[u].size();
for(int i=0;i<num;i++)
{
int v=gr[u][i];
if(v!=f && d<k) ddfs(v,u,d+1);
}
}
int slove()
{
int ans=0;
memset(vis,0,sizeof(vis));
for(int d=n-1;d>k;d--)
for(int i=0;i<nodes[d].size();i++)
{
int u=nodes[d][i];
if(vis[u]) continue;
int v=u;
for(int j=0;j<k;j++) v=fa[v];
ddfs(v,-1,0);
ans++;
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
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",slove());
}
}