问题
https://vjudge.net/problem/UVA-1267
分析
本题只需要覆盖叶子。
无根树变为有根树,对于当前没有被覆盖的最深的叶节点,选择它的k级祖先作为服务器,然后消除被覆盖的叶节点。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn=1005,Inf=0x3f3f3f3f;
int T,n,s,k,kase=0,a,b,fa[maxn],vis[maxn];
vector<int> graph[maxn],leaf[maxn];
void getFa(int u,int v,int d){
if(graph[u].size()==1) {
if(d>k+1)
leaf[d].push_back(u); //leaf[d]=u代表深度为d时有一个u点未被覆盖,d>=1
return;
}
for(int i=0;i<graph[u].size();++i){
int t=graph[u][i];
if(t==v) continue;
fa[t]=u;
getFa(t,u,d+1);
}
}
void dfs(int cur,int pre,int d){
if(d>=k) return;
for(int i=0;i<graph[cur].size();++i){
int t=graph[cur][i];
if(t==pre) continue; //可以访问父节点,只要和cur距离不超过k的点都可以
vis[t]=1;
dfs(t,cur,d+1);
}
}
int solve(){
int ans=0;
for(int i=n;i>0;--i){
for(int j=0;j<leaf[i].size();++j){
int t=leaf[i][j];
if(!vis[t]){
vis[t]=1;
int f=fa[t];
for(int step=1;step<k;++step){
f=fa[f];
}
vis[f]=1;
++ans;
dfs(f,-1,0);
}
}
}
return ans;
}
int main(void){
scanf("%d",&T);
while(kase<T){
scanf("%d%d%d",&n,&s,&k);
for(int i=1;i<=n;++i) {
graph[i].clear();
leaf[i].clear();
}
for(int i=1;i<n;++i){
scanf("%d%d",&a,&b);
graph[a].push_back(b);
graph[b].push_back(a);
}
memset(fa,-1,sizeof(fa));
getFa(s,-1,1);
memset(vis,0,sizeof(vis));
printf("%d\n",solve());
++kase;
}
return 0;
}
该博客主要分析了如何使用贪心策略解决UVA在线判题中的1267题。问题涉及将无根树转化为有根树,通过选择每个未被覆盖的最深叶节点的k级祖先作为服务器,以此消除覆盖的叶节点。

1387

被折叠的 条评论
为什么被折叠?



