zoukankan      html  css  js  c++  java
  • 【POI每日题解 #8】DYN-Dynamite

    你问蒟蒻为什么一天写两篇每日题解?

    难道每日坚果你不能一天吃两包吗?

    题目链接

    …这道题第一反应就是二分答案【太明显了

    枚举答案 就那个“关键节点到这些点中距离的最小值的最大值”【蒟蒻读了好几遍……

    若枚举到mid 则判定答案为mid时,覆盖所有特殊点的最少点数能否不超过m

    这很点分治

    对于一个子树 我们要处理到它里面没有没被覆盖的点

    或者有到该子树根距离小于mid的【它可以放在以后解决

    那什么时候要选点呢?

    自然是上面两个条件都不满足的时候

    也就是离子树根最远的未被覆盖特殊点到子树根的距离等于mid 【注意边权为一,大于就来不及了

    所以对每棵子树存储它未被处理的最远特殊点的距离

    注意到一个节点连接的两棵子树可以互相覆盖

    并且覆盖所经过的路径必然经过当前节点

    因此 记录到每个根节点距离最近的已选点的距离

    至此 维护两个值 点分治得以完成

    蒟蒻一开始没想到能A这道题 随便一写一交【当然这习惯很不好

    60了【facepalm  稍微debug下就A了……

    但以后还是不要这么干…… 以此为戒

    注意 对于1(根节点) 要进行特判

    因为此时按点分治 到根节点距离小于mid的特殊点仍被保留

     1 void dfs(int x, int fa){
     2     d1[x] = sp[x] ? 0 : -N; d2[x] = N;
     3     for(int i = head[x]; i != -1; i = edge[i].next){
     4         int vv = edge[i].v;
     5         if(vv == fa) continue;
     6         dfs(vv, x);
     7         if(d1[vv] != -N) d1[x] = max(d1[x], d1[vv] + 1);
     8         d2[x] = min(d2[x], d2[vv] + 1);
     9     }
    10     if(d1[x] + d2[x] <= mid) d1[x] = -N;//!!!
    11     if(d1[x] == mid){
    12         tot++; d1[x] = -N; d2[x] = 0;
    13     }
    14     if(sp[x] && d2[x] > mid)
    15         d1[x] = max(d1[x], 0); //!!!
    16 }
    17 
    18 inline bool check(){
    19     tot = 0;
    20     dfs(1, 1);
    21     if(d1[1] + d2[1] > mid) tot++;//!!!
    22     return tot <= m;
    23 }
    check
  • 相关阅读:
    ubuntu 14.04下使用fcitx时将caps lock映射为ctrl
    php多进程、IPC和事件驱动
    [轉載]【京都动画统治世界】短篇科幻小说《2134动漫奇缘》
    [日语]每日笔记
    [转载]C++的顺序点(sequence point)和副作用(side effect)
    [转载]Best Practices for Speeding Up Your Web Site
    [系统]安装fedora 19
    阿里云服务上面部署redis + 本地Redis客户端连接方法 + 配置redis服务
    linux [Centos7]搭建PHP的RabbitMQ环境
    linux vim常用操作
  • 原文地址:https://www.cnblogs.com/hjmmm/p/9232354.html
Copyright © 2011-2022 走看看