您的位置:首页 > 其它

51nod 1378:夹克老爷的愤怒

2017-04-19 16:14 267 查看
[b]51nod 1378:夹克老爷的愤怒[/b]

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1378

题目大意:给出一颗结点为​$n(1 \leqslant n \leqslant 100000 )$的树,若每设置一个点使得距离该点不超过$k(0\leqslant k \leqslant n )$​的结点均被覆盖,问全部覆盖整颗树需要设置的最少的点为多少.

贪心

显然从叶结点开始向根延伸,每到必须放置的时候放置一个点,遍历到根时若根没被覆盖则放置点个数$+1$,这种方法得到的放置点个数最少(考虑若从根开始向叶结点延伸,遍历到叶节点时若叶节点没被覆盖则放置点个数$+M$,$M$为没被覆盖的叶节点数).

具体操作为dfs返回每个点向上未被覆盖的距离$dis(-k \leqslant dis \leqslant k)$.

对于结点$u$,维护其每个孩子$v$返回$dis$的最大值$maxn$及最小值$minn$,若$maxn \leqslant k$,则在结点$u$放置覆盖点.

复杂度为$O(n)$.

代码如下:

#include <cstdio>
#include <vector>
#define N 100005
using namespace std;
int ans,x,y,n,k;
vector<int>e
;
int dfs(int x,int f){
if(e[x].size()==1&&e[x][0]==f)return 1;
int minn=k+1,maxn=-k-1;
for(int i=0;i<(int)e[x].size();++i)if(e[x][i]!=f){
int d=dfs(e[x][i],x);
maxn=max(maxn,d);
minn=min(minn,d);
}
if(maxn>=k){
ans++;
return -k;
}else return (minn+maxn<0?minn:maxn)+1;
}
int main(void){
scanf("%d%d",&n,&k);
for(int i=1;i<n;++i){
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
if(k==0){
printf("%d\n",n);
}else{
if(dfs(0,-1)>0)ans++;
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: