1. 基础贪心:邻项交换与证明
贪心算法的精髓在于“局部最优”导向“全局最优”。然而,其正确性并非总是显而易见的,需要严谨的数学证明。邻项交换(Exchange Argument)是证明一类排序相关贪心策略最经典、最强大的武器。其核心思想是:假设存在一个不同于贪心解的最优解,我们可以通过一系列“邻项交换”操作,在不降低解的质量的前提下,逐步将该最优解调整为贪心解。
这个过程通常遵循反证法。我们假设最优解 \(S_{opt}\) 在某个位置首次与贪心解 \(S_{greedy}\) 出现差异。设贪心策略是基于某种排序规则,我们将最优解中不符合该规则的相邻元素进行交换。关键在于证明这次交换不会使解变得更差。如果能证明这一点,我们就能说明任何最优解都可以被转化为贪心解,从而证实了贪心策略的正确性。例如,在经典的活动安排问题中,按结束时间排序的贪心策略,其正确性就可以通过邻项交换来完美证明。从更抽象的视角看,这构建了一个从任意最优解到特定贪心解的“路径”,确保了贪心解的“最优性代表”地位。
2. 最短路 (一):核心算法概览
最短路问题是图论的基石,不同算法适用于不同场景,其背后蕴含着动态规划与贪心思想的交辉。
- Bellman-Ford & SPFA:两者都基于动态规划的松弛(Relaxation)操作,能处理带负权边的图。Bellman-Ford算法执行 \(V - 1\) 轮迭代,每轮对所有边进行松弛,其状态转移方程可视为 \(d(k, v) = \min_{u \to v} \{ d(k - 1, u) + w(u, v) \}\) ,表示最多经过 \(k\) 条边到达 \(v\) 的最短路。SPFA(Shortest Path Faster Algorithm)是Bellman-Ford的队列优化版本,它只将距离被更新的节点重新入队,在稀疏图和随机数据上表现出色,但其最坏复杂度与Bellman-Ford相同,且在特定构造的图上容易被卡到上限。两者的共同优势在于能够检测负权环。
Dijkstra: 这是一种基于贪心策略的算法, 要求所有边权非负。它维护一个已确定最短路径的顶点集合 \(S\) , 每次从未在 \(S\) 中的顶点中, 选取一个距离源点最近的顶点 \(u\) 加入 \(S\) , 并用 \(u\) 来松弛其所有出边。正确性的根基在于, 当边权非负时, 一旦一个顶点的最短路被确定, 它不可能再被其他路径更新。使用优先队列 (如二叉堆) 优化后, 其复杂度为 \(O(E \log V)\) 。 - Floyd-Warshall:用于计算任意两点间(All-Pairs)的最短路。它采用动态规划思想,其核心状态 \(d(k, i, j)\) 表示从 \(i\) 到 \(j\) 只允许经过编号为1到 \(k\) 的顶点的最短路径长度。状态转移方程为: \(d(k, i, j) = \min(d(k - 1, i, j), d(k - 1, i, k) + d(k - 1, k, j))\) 其 \(O(V^3)\) 的复杂度使其适用于稠密图。
- Johnson: 在稀疏图上解决带负权边的全源最短路问题。它巧妙地结合了 Bellman-Ford 和 Dijkstra: 首先, 新建一个虚拟源点 \(s\) , 向所有顶点连一条权值为 0 的边, 然后用 Bellman-Ford 计算到所有顶点的最短路 \(h(v)\) 。若无负环, 则将每条边 \((u, v)\) 的权值 \(w(u, v)\) 更新为 \(w'(u, v) = w(u, v) + h(u) - h(v)\) 。可以证明新的边权 \(w'\) 非负, 且任意两点间的最短路径在新图中保持不变 (路径长度的增量为常数)。之后对每个点运行一次 Dijkstra 即可。
- 差分约束系统:这是一种将特定形式的不等式组与最短路问题联系起来的优美模型。对于一组形如 \(x_{j} - x_{i} \leq c_{k}\) 的不等式,我们可以构造一张图,其中每个变量 \(x_{i}\) 对应一个节点。对于每个不等式 \(x_{j} - x_{i} \leq c_{k}\) ,我们从节点 \(i\) 向节点 \(j\) 连一条权值为 \(c_{k}\) 的边。求解这组不等式等价于在该图上求解最短路。若图中存在负权环,则不等式组无解。