题目链接:点击打开链接
题意:n台机器连成一个树状网络,其中叶节点是客户端,其他节点是服务器,目前有一台服务器s正在提供服务。让你在其他服务器上也安排同样的服务,使得每台客户端到最近服务器的距离不超过k,而且要使服务器尽量少,问最少要设置多少台服务器。
思路:我们先把s看做根节点,做一遍dfs,把离s距离小于等于k的叶子节点标为访问过,表示这个叶子节点已经得到服务了,然后再把没有访问过的叶子节点按深度从大到小排序,每次找到深度最大的点,在它的k倍祖先上放服务器,然后dfs一遍,把离它距离不超过k的叶子节点都标为访问过。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<bitset> #include<algorithm> using namespace std; typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) #define maxn 1005 #define MOD 1000000009 vector<int>vec[maxn]; vector<int>deep[maxn]; vector<int>::iterator it; int vis[maxn],fa[maxn]; int k; void dfs(int u,int pre,int dep) { int i,j,flag=0; fa[u]=pre; if(dep+1<=k+1)vis[u]=1; for(i=0;i<vec[u].size();i++){ int v=vec[u][i]; if(v!=pre){ flag=1; dfs(v,u,dep+1); } } if(!flag)deep[dep+1].push_back(u); } void dfs2(int u,int pre,int num) { int i,j; vis[u]=1; if(num==k)return; for(i=0;i<vec[u].size();i++){ int v=vec[u][i]; if(v!=pre){ dfs2(v,u,num+1); } } } int main() { int n,m,i,j,T,s,c,d,h; scanf("%d",&T); while(T--) { scanf("%d",&n); scanf("%d%d",&s,&k); for(i=1;i<=1003;i++){ vec[i].clear(); deep[i].clear(); } memset(fa,0,sizeof(fa)); memset(vis,0,sizeof(vis)); for(i=1;i<=n-1;i++){ scanf("%d%d",&c,&d); vec[c].push_back(d); vec[d].push_back(c); } dfs(s,0,0); int cnt=0; for(h=n;h>k+1;h--){ for(i=0;i<deep[h].size();i++){ if(vis[deep[h][i] ])continue; int jiedian=deep[h][i]; for(j=1;j<=k;j++){ jiedian=fa[jiedian]; } cnt++; dfs2(jiedian,-1,0); } } printf("%d\n",cnt); } return 0; } /* 100 10 1 1 1 2 1 3 1 4 2 5 2 6 3 7 3 8 5 9 5 10 */