【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

 

转载于:https://www.cnblogs.com/hjmmm/p/9232354.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值