题目链接:点击打开链接
题意:一开始只有一个结点上有一个服务器, 为了让所有叶子结点距离服务器的距离不超过k, 我们在非叶子结点上添加服务器, 问最少添加多少服务器。
思路:贪心。 将第一个服务器所在结点作为根结点, 向下拓展, 记录父子关系, 将叶子结点的深度排序, 从最深的结点开始向上找k个距离的父节点, 安装服务器, 并进行一次DFS, 将所有距离它不超过k的结点标记。
细节参见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;
const int mod = 1000000000 + 7;
const int INF = int(1e9);
const ll INF64 = ll(1e18);
const int maxn = 1000 + 10;
int T,n,m,s,k,root,p[maxn];
bool vis[maxn];
struct node {
int u, d;
node(int u=0, int d=0):u(u), d(d) {}
bool operator < (const node& rhs) const {
return d < rhs.d;
}
};
vector<int> g[maxn];
vector<node> d;
void pre(int u, int fa, int cur) {
int cnt = g[u].size();
p[u] = fa;
if(cnt == 1) { d.push_back(node(u, cur)); return ; }
for(int i=0;i<cnt;i++) {
int v = g[u][i];
if(v != fa) {
pre(v, u, cur+1);
}
}
}
void dfs(int u, int fa, int cur) {
if(cur > k) return ;
int len = g[u].size();
vis[u] = true;
for(int i=0;i<len;i++) {
int v = g[u][i];
if(v != fa) {
dfs(v, u, cur+1);
}
}
}
int u, v;
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d%d%d",&n,&s,&k);
for(int i=1;i<=n;i++) g[i].clear();
d.clear();
for(int i=1;i<n;i++) {
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
pre(s, s, 0);
sort(d.begin(), d.end());
memset(vis, false, sizeof(vis));
dfs(s, s, 0);
int len = d.size();
int ans = 0;
for(int i=len-1;i>=0;i--) {
node u = d[i];
if(vis[u.u]) continue;
int v = u.u;
for(int j=0;j<k;j++) v = p[v];
dfs(v, v, 0);
++ans;
}
printf("%d\n",ans);
}
return 0;
}