分数规划小结
Preface
其实分数规划就是化下式子,然后套个二分就没了... 所以分数规划的问题的核心并不在分数规划的部分
Description
给你\(n\)个元素,每一个元素都有两个权值\(a_i, b_i\),你需要选择若干个元素,最大/小化\(\frac{\sum a_i}{\sum b_i}\)
Process
我们可以先二分一个答案每次只需要判断和不合法即可,假设答案为\(ans\),并且需要最大化分数
这样我们就只需要令一件物品的权值\(w_i = a_i - ans \cdot b_i\),然后判断是否能选出一些物品使得\(\sum w_i \geq 0\)即可
2分钟讲完分数规划
Problem
[POJ2976] Dropping tests
给你\(n\)个物品,每一个物品都有两个权值\(a_i, b_i\),你需要选出\(k\)个物品,最大化
答案四舍五入至整数
\(n \leq 1000, 0 \leq k < n\)
Solution
这就是一道板子题,直接照着前面的方法做
<p>每次对$w_i$排一遍序,然后取最大的$k$个加起来看是不是大于等于$0$就可以了</p>
[Luogu4322] 最佳团体
给你一棵树(点编号\(0\)~\(n\)),每一个节点都有两个属性\(p_i, s_i\)
你需要在树上选择\(k + 1\)个节点,并且选择一个节点的前提选择它的父亲节点(根结点除外),并且最大化\(\frac{\sum p_i}{\sum s_i}\)
\(k \leq n \leq 2500\)
Solution
就直接套一个分数规划,然后再做一遍树形依赖背包就可以了
<p>考虑到可能会有$10^{-10}\%$的人像我一样,可能会不知道树形依赖背包,所以我还是讲一下</p>
<p>我们可以把这棵树转换为$dfn$序,然后就可以在dfn序上$dp$了,设$sz[x]$为以$x$为根的子树的大小</p>
<p>有转移方程
$$
dp[i][j] = max(dp[i + 1][j - 1], dp[i + sz[i]][j])
$$
最后答案就是$dp[0][k + 1]$</p>
<p><a href = "https://paste.ubuntu.com/p/Mct5ztjHN5/">Code</a></p>
[Luogu3199] [HNOI2009]最小圈
给你一个\(n\)个点\(m\)条边的带权有向图,你需要找到这个图中最小权值的环
定义一个环的权值为这个环上所有边边权的平均值
Solution
对于这种题目,我们可以对其建模,然后转换为分数规划问题
<p>我们可以令每一条边有两个边权$a_i, b_i$,其中$a_i$等于边权,$b_i$等于$1$</p>
<p>然后就直接套分数规划,然后判断有没有负环就可以了</p>
[POJ2728] Desert King
一个国家有\(n\)座城市,每一个城市都有一个坐标\(x_i, y_i\)和一个海拔\(h_i\)
你需要在城市之间修建恰好\(n - 1\)条道路,使得所有的城市之间都可以互相到达
一条道路的长度为两个端点的欧几里得距离,花费为端点的海拔差
现在你需要修建这些道路,并且要最小化总花费与总长度的比值,输出这个比值
\(n \leq 1000\)
Solution
首先看到比值,就直接转化为分数规划问题
<p>不难发现,如果直接每次用$kruskal$跑最小生成树显然是会T的,因为可能是完全图</p>
<p>所以我们可以写一个$n^2$的prim来跑 (这东西虽然平时用的不多,但搞稠密图还是有一点用的)</p>
<p><del>另外,本题莫名卡精度</del></p>
<p><a href = "https://paste.ubuntu.com/p/cXTZPzckm4/">Code</a></p>
[Luogu2868] [USA07DEC]观光奶牛
给你一个有向图,每一个点有一个权值\(f_i\),每一条边有一个权值\(w_i\)
你需要选择一个点,然后以这个点为起点,遍历若干个节点(至少两个)然后回到原点。这时你的快乐值为\(\frac{\sum f_i}{\sum w_i}\)(多次经过一个点只算一次\(f_i\),\(w_i\)可以多次计算)
请问最大的快乐值为多少
Solution
我们先套一个分数规划之后,把一条边的权值看成$b_i$,它所指向的点看成$a_i$,不难发现就是要求一个负环
<p>但是多次经过一个点只会计算一次的限制有怎么处理呢?</p>
<p>我们可以发现如果一个复杂环为负数,那么构成这个复杂环的简单环中至少有一个为负数,所以找到哪个负环都是等价的</p>