[算法相关]wqs 二分
Posted Dfkuaid
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[算法相关]wqs 二分相关的知识,希望对你有一定的参考价值。
简述
闲话
wqs 二分最初由王钦石在他的 2012 年国家集训队论文中提出,而从 IOI 2016 的 Aliens 题目开始,这种方法开始逐步在竞赛圈中有了一定的地位。在国内我们一般称为「wqs 二分」,而在国外一般称为「Alien Trick」。
常见适用范围
应用 wqs 二分的一种常见的问题形式为:给定一些带有价值的物品,价值可以为负,对于物品的选择具有一定限制,求选定物品总价值最大/最小值。
大致思想
屑在前面
为了方便下面的讲解,这里结合例题 Tree I 来进行讲解。
题目大意:有一张无向带权连通图,每条边要么是黑色要么是白色,现指定要找到一棵恰有 \\(N\\) 条白边的最小生成树,输出最小边权和。
首先,我们将这个题面与上面的适用范围进行对号入座,“带权边”是“有价值的物品”,“恰有 \\(N\\) 条白边”和“生成树”都是“限制”,“最小生成树”意味着求最小值。
设计函数
我们首先设计函数 \\(f(x)\\) 表示当恰选择 \\(x\\) 条白边时的最小生成树权值和,容易发现在一个定值 \\(x=c\\) 前 \\(f(x)\\) 一定是单调递减的,因为此时存在一条白边的权值小于选定边集中的黑边最大边权,于是此时随着需要的白边的数量增长,一定可以用边权更小的白边换掉边权较大的黑边,使得总边权变小;达到 \\(c\\) 后,每次用白边替换黑边一定会使得总的边权和变大,于是之后函数应当是单调递增的,可以看出函数图像应当是一个下凸壳,于是函数图像应当大致如下:
而且显然有
这一点考虑 \\(f(x)\\) 的定义并采用反证法证明不难。也就意味着图像雀雀食食是下凸壳。
利用图像
现在我们得到了一个下凸壳,那么我们该如何利用呢?我们知道,对于任意一个斜率,一定最多有一条为该斜率的直线与凸壳相切与某一点;而且可以发现,对于本题的凸壳,斜率越小,对应的切点的横坐标一定越小,因而我们可以尝试二分这个斜率,来尝试得到这个切点,假设我们能够求得对应的 \\(x\\) 及 \\(f(x)\\),我们就可以确定下一步二分的斜率应该更大还是更小,并得到对应的最小值。
那么,我们就需要知道如何计算 \\(x\\) 及 \\(f(x)\\)。首先,我们知道一个下凸壳的性质:对于同一斜率 \\(k\\) 的直线过凸壳上一点,过切点的直线的纵轴截距最小,如下图所示。
根据直线方程,不难得到该截距为
意味着 \\(g(x)\\) 为选取 \\(x\\) 条白边时,每条白边价值减 \\(k\\) 后,此时能拿到的最优解。
这里给出一个性质:切点上的 \\(g(x)\\) 为每一条白边价值减去 \\(k\\) 后,没有额外限制(即不限制白边数量)选取得到的全局最优解。
这个结论看起来总觉得怪怪的,给人一种想推翻它的冲动,但是我们来看:对于任意一点 \\((x,f(x))\\),对应的是选取恰好 \\(x\\) 个白边时对应的最优解,加入我们将所有边的边权都减少 \\(k\\),显然任意两条边之间的相对大小关系是不变的,那么选择的边集并不会改变,于是这个最优解就变为了 \\(f(x)-k\\cdot x\\),也就是 \\(g(x)\\),也就是直线的纵轴截距;而根据我们上面提到的下凸壳的性质,我们可以知道,过切点 \\((a,f(a))\\) 的直线的纵轴截距一定是所有截距中最小的,也就是所有 \\(g(x)\\) 中最小的,于是也就是不加限制选择白边的最优解,注意得到该最优解需要选出的白边数量一定是 \\(a\\),而加上 \\(k\\cdot a\\) 得到的就是 \\(f(a)\\).
于是我们就可以在每一次二分斜率 \\(k\\) 后,直接求出当前每个白边边权减小 \\(k\\) 后任意选的最优解,同时记录最优解需要的白边数量 \\(x\\),再把价值加上 \\(k\\cdot x\\) 就得到了所需的数据。
细节处理
事实上,真实的图像有可能是这样的:
注意到,图中的点 \\(I\\) 是无法被直线恰好切到的,因为它两边的直线的斜率相等,那么该如何处理?
我们可以使每次选取边时,对于权值相同的边,优先选白边,这样,我们得到的“切点”就是点 \\(F\\),在二分时我们保存的直线的斜率应当是满足需要的白边数大于等于 \\(N\\) 中的最小斜率,这样我们可以保证得到的斜率 \\(k\\) 正确,一定可以得到正确的纵轴截距,最后单独加上 \\(k\\cdot N\\) 即可。
代码实现
咕咕咕
简单总结
从上面的过程不难看出, wqs 二分适用于价值函数为上/下凸壳的情况,可以巧妙地将原本选择的部分限制去掉,从而优化算法。
同时如果遇到了图像上的一些特殊情况,可以对 check()
与二分函数进行简单的修改,从而达到所要的效果。
参考文章
以上是关于[算法相关]wqs 二分的主要内容,如果未能解决你的问题,请参考以下文章
CF739EGosha is hunting(WQS二分套WQS二分)