zoukankan      html  css  js  c++  java
  • 51nod 1378:夹克老爷的愤怒

    51nod 1378:夹克老爷的愤怒

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

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

    贪心

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

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

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

    复杂度为$O(n)$.

    代码如下:

     1 #include <cstdio>
     2 #include <vector>
     3 #define N 100005
     4 using namespace std;
     5 int ans,x,y,n,k;
     6 vector<int>e[N];
     7 int dfs(int x,int f){
     8     if(e[x].size()==1&&e[x][0]==f)return 1;
     9     int minn=k+1,maxn=-k-1;
    10     for(int i=0;i<(int)e[x].size();++i)if(e[x][i]!=f){
    11         int d=dfs(e[x][i],x);
    12         maxn=max(maxn,d);
    13         minn=min(minn,d);
    14     }
    15     if(maxn>=k){
    16         ans++;
    17         return -k;
    18     }else return (minn+maxn<0?minn:maxn)+1;
    19 }
    20 int main(void){
    21     scanf("%d%d",&n,&k);
    22     for(int i=1;i<n;++i){
    23         scanf("%d%d",&x,&y);
    24         e[x].push_back(y);
    25         e[y].push_back(x);
    26     }
    27     if(k==0){
    28         printf("%d
    ",n);
    29     }else{
    30         if(dfs(0,-1)>0)ans++;
    31         printf("%d
    ",ans);
    32     }
    33 }
  • 相关阅读:
    [转]C++ Operator Overloading Guidelines
    SICP学习笔记(2.2.1)
    .net中模拟键盘和鼠标操作
    javaScript系列 [17]运算符
    javaScript系列 [24]Math
    javaScript系列 [19]string
    javaScript系列 [22]引用类型
    javaScript系列 [12]Canvas绘图(曲线)
    javaScript系列 [15]Canvas绘图(压缩)
    javaScript系列 [21]Array
  • 原文地址:https://www.cnblogs.com/barrier/p/6734029.html
Copyright © 2011-2022 走看看