题目:Network
思路:
将无根树转为有根树,并在最深的不满足条件的叶子的上k层放服务器,循环操作,直到无法放置新的服务器。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
#include <cmath>
using namespace std;
#define maxn 1000
struct Node {
int x,fa,d;
Node() {}
Node(int xx,int faa,int dd) {
x=xx,fa=faa,d=dd;
}
bool operator <(const Node& y) const {
return d>y.d||(d==y.d&&x<y.x);
}
};
int n;
int s,k;
vector<int> a[maxn+5]; //原图
vector<Node> lvs; //叶子
bool lvs2[maxn+5]= {0};
int fa[maxn+5],dpth[maxn+5];
bool p[maxn+5]; //标记
void init() {
for(int i=1; i<=maxn; i++) a[i].clear();
lvs.clear();
memset(p,0,sizeof(p));
memset(lvs2,0,sizeof(lvs2));
}
void make(int x,int f,int d) { //把无根树转为有根树,计算fa和dpth
fa[x]=f,dpth[x]=d;
if(1==a[x].size()) {
lvs.push_back(Node(x,f,d));
lvs2[x]=true;
return ;
}
for(int i=0; i<a[x].size(); i++) {
int y=a[x][i];
if(y==f) continue;
make(y,x,d+1);
}
return ;
}
void dfs(int u,int x,int d) { //标记在添加u后满足条件的叶节点
if(d>k) return ;
if(lvs2[x]) p[x]=true;
for(int i=0; i<a[x].size(); i++) {
dfs(u,a[x][i],d+1);
}
}
int find(int x){ //找到放服务器的点
for(int i=1;i<=k;i++){
x=fa[x];
}
return x;
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
init();
scanf("%d%d%d",&n,&s,&k);
for(int i=1; i<n; i++) {
int x,y;
scanf("%d%d",&x,&y);
a[x].push_back(y);
a[y].push_back(x);
}
make(s,-1,0);
sort(lvs.begin(),lvs.end());
for(int i=0;i<lvs.size();i++){
int x=lvs[i].x;
}
int ans=0;
dfs(s,s,0);
for(int i=0; i<lvs.size(); i++) {
if(p[lvs[i].x]) continue;
int x=find(lvs[i].x);
ans++;
dfs(x,x,0);
}
printf("%d\n",ans);
}
return 0;
}