「NOIP2012」疫情控制 题解

1 题面

「NOIP2012」疫情控制

2 分析题面

2.0 题目简述

有一棵n个节点的,根为1的带权树和m支军队。现在有m支军队已经在某些点上,移动一支军队到一个相邻的点所花时间等于该条边的边权。军队可同时移动。问至少多少时间才可以使从1开始都到不了任何一个叶子节点(无法满足条件输出-1,根节点不能停军队)。

[概要]

题目相当于在一棵树上,用给定的军队去把这棵树的所有子树全部占领。求最大移动距离的最小值。

2.1 考虑算法

2.1.1 二分

这道题是要求最大移动距离的最小值即最少的时间,考虑二分答案

2.1.2 贪心

让每支军队尽可能向根节点爬

因为军队越往上,能封住的叶子节点就越多。在能往上的情况下,尽可能往上

一支军队如果不能到根节点,就让其在能走到的最高点停下,并封锁这个节点

再然后,用剩下的能到达根节点的军队去覆盖

然后对于一个节点,用剩余时间最少的,且比这个节点到根节点的距离大的军队覆盖

[注意]如果一个军队经过的根节点的儿子没有被覆盖,则优先覆盖

2.1.3 倍增预处理

对于让军队向上走的过程,我们可以用倍增的方法进行优化,所以要先预处理

时间复杂度 O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)

2.2 画图理解

如果以上讲解没有听懂,可以借助下面这组数据更详细地了解:

10 5
2 1 3
2 3 4
1 4 7
5 1 9
6 1 2
4 7 9
7 8 8
9 8 8
1 10 2
2 8 5 4 2 

假设我们当前二分到的时间限制为9,模拟上面的步骤进行一遍。

  1. 上移军队:只有处于节点8的军队上移到了节点7,其余节点由于都在根节点的子节点上,不动。

  2. 找出闲置军队与需要被驻扎的节点。显然,闲置军队为目前处于4、2、5节点上的4支军队,需要被驻扎的节点为10、2、5、6节点。

  3. 初步处理这些数据。由于5号节点上的军队无法到达根节点再返回,且该节点需要被驻扎,因此该军队驻扎在五号节点;同理,7号节点上的军队驻扎在七号节点。

  4. 找出目前的闲置军队和需要被驻扎的节点。剩余的闲置军队为目前处于4、2节点上的3支军队,需要被驻扎的节点为2、6、10号节点。

  5. 利用贪心策略进行最后的匹配。最后,4号节点上的军队驻扎到6号节点,2号节点上的两支军队分别驻扎到2、10号节点。该方案是可行的。

3 代码实现

3.1 输入

没什么好说的

for(int i=1; i<n; i++){
   
    scanf("%d%d%d",&x,&y,&z);
    //建边
}
//预处理
scanf("%d",&m);
for(int i=1; i<=m; i++){
   
    scanf("%d",&army[i]);//输入军队
}

3.2 预处理

节点的深度越小,控制的节点(子树内的节点)越多。所以可以贪心地把军队尽量向上提。

据此,我们需要把每个点往上的距离预处理,用倍增优化。

void dfs(int x,int l, ll hg){
   
    f[x][0]=l,dis[x][0]=hg;
    for(int i=1; i<=t; i++){
   
        f[x][i]=f[f[x][i-1]][i-1];
        dis[x][i]=dis[x][i-1]+dis[f[x][i-1]][i-1];
    }//递推
    for(int i=hd[x]; i!=-1; i=nxt[i]){
   //遍历x的出边
        if(to[i]!=l){
   
            dfs(to[i],x,e[i]);
        }
    }
}//树上倍增预处理

3.3 二分答案

根据前面的分析,我们在 check 的时候要尽量把军队往上走

当二分答案后,设答案为 k,这里会有两种情况

3.3.1 可以到达

最高的位置一定是最优的,让他待在那里

3.3.2 无法到达

那求出他到达后还可以走多少时间 以及到达 <

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值