贪心
1 调整法证明贪心
考虑证明某一种方案是最优策略的时候,这样证明:对于解集合里的其他所有解,都存在一种调整使得其变得更优,说明其他解都不是最优解。这里来看两个例子:
1.1 最小生成树的内核和证明
首先感性去看一下这个问题。一棵生成树的核心是把一些点联合在一起。我们会想到,对于一个集合,与其他点连接起来的时候,是不是去使用一条边权最短的向外连边会最优秀呢?其实是这样的,而这就是 Boruvka 算法在干的事情。而我们审视一下 Kruskal 在干的事情,其实是 Boruvka 的另一种表达方式:当前时刻一条集合之间的最短连边,不就是我们的 Boruvka 要找的吗!
所以这两种算法是统一的。对于它们之间的关系,我更倾向于是类似四边形不等式中二元形式和四元形式的区别:四元形式是最本质的东西,二元形式是换一种表达方式,但是其更可以证明,也更可以启发出一些性质。Kruskal 因为重新表达了 Boruvka,生成了一个以一条边为单位分层的算法,所以性质更好,更好证明。
oi-wiki 上有一个证明,我认为其实并没有从本质出发去证明它,这里介绍另一种证明方法,运用了开头所说的这个思想,其和 oi-wiki 上的证明是本质相同的,但是使用了贪心的巧妙策略,其思路是可复现的:
考虑一种生成树方案 \(T\)。考虑其第一个和 Kruskal 找到的生成树 \(\mathcal T\) 不一样的边。\(\mathcal T\) 中这一步本该连接的 \(i\) 和 \(j\) 我们暂时不连,之后有一条边将 \(i\) 和 \(j\) 所在的集合连通(这是良定义的,如同树上背包一样是可以考虑两个点什么时候连通的)。那么交换这两条边,其他边都不进行改变,会变得更优。于是这种方案并非是最好的。
1.2 树上全序问题的贪心策略证明
usaco 2023 Feb 金组 T2
【题意】FJ 有一颗树,每个节点初始都有一个草苗高 \(0\) 厘米,每一秒会长 \(a_i\) 厘米草。FJ 一开始在根节点,走一条边的时间是一秒,第一次走到某个节点的时候,花费该节点草高的代价,拔起这根草,这个节点之后不会再长草。FJ 要拔掉所有草,问:
- 如果必须返回根节点,那么最小代价是?
- 如果必须走到某一个深度最深的节点,那么最小代价是?
【分析】
首先我们大概看看发现是需要给儿子排个序然后依次经过。
然后我们首先分析一下第一问的情况下按照什么排序。如果一棵树从 \(0\) 时刻开始进入,有若干个节点按走的顺序标号 \(son_1, son_2, ..., son_k\),那么其时间为 \(\sum \limits_{i = 1} ^ k (\sum \limits_{j \in subtree_i} a_j \times \sum \limits_{j = 1}^{i - 1} size_{son_j} \times 2) + dp_{i}\),其中 \(dp_{son_i}\) 表示的是 \(0\) 时刻进入 \(son_i\) 需要花多少时间采完。
考虑怎么把贡献拆到每个儿子手上。这里证明对于某一个特定满足邻项交换不优性质的顺序,如果数组不是按照这个排序,那么一定有逆序对,那么一定有相邻逆序对,那么交换这个对一定不会劣。于是这个数组不优,因此只有按照这个顺序排序后数组是最优的。
那么邻项交换不优性质看看有没有。这比较容易,因为前和后贡献没有改变,而对于两个儿子 \(i, j\),其自己的贡献是:如果 \(i\) 在前 \(dp_i + sum_j \times size_{i} \times 2 + dp_j\),否则 \(dp_j + sum_i \times size_{j} \times 2 + dp_i\),其中 \(sum_i\) 表示子树 \(a_i\) 和。
那么显然前面大于后面的条件就是 \(\cfrac{size_{i}}{sum_i} < \cfrac{size_{j}}{sum_j}\),这可以写成 cmp。
于是有了这个性质,加上加粗理论,我们得到了一个正确的排序方法。可以说没有加粗理论,根本没有做出这类树的全序题的可能。至于第二问,不在讨论范围内,先不管了。
ABC304Ex. Constrained Topological Sort
给定一张有向图,求一个拓扑序,使得对于每一个 \(i\) 都有 \(l_i \le rnk_i \le r_i\) 成立。
\(n \le 2 \times 10^5, m \le 4 \times 10^5\)
考虑将限制变得真实:对于 \(i \rightarrow j\),令 \(r_i \min = r_j - 1,l_j \max = l_i + 1\)。然后每一次将可以选择的点(\(l_i\) 到了时间并且所有父亲都已经选了)放到 pq 里,选 \(r_i\) 最小的那个点,就是最优方案。
感性理解挺对的,因为儿子因为父亲没选被拖累了这种事不是不得已不会发生。
理性证明不会。
2 反悔贪心
遇到一个问题:有 \(n\) 个位置,一个位置上可能有 \((, )\) 或者两者可以选一个的 \(?\)。求最大括号匹配。
这个问题可以反悔贪心,维护两个集合,分别维护可以匹配的左端点,以及目前做了 \()\) 的通配符,对于一个 \((\),直接加入第一个集合;对于一个 \()\),考虑第一个集合是否非空,如果是就匹配,否则考虑第二个集合是否有元素,如果有,令其成为 \((\),并且当前这个括号和原来这个通配符所匹配的元素匹配。对于一个 \(?\),首先判断是否可以成为 \()\),如果可以的话要注意加入第二个集合;否则加入第一个集合。
证明什么,感觉就是,感受那股劲!(xhz 名言:它显然每一步都最优,所以就是对的!)