最小割树

lolifamily

注意!

  • 在边很多的时候用邻接矩阵,边很少时要用前向星
  • 2 开始循环!

题目大意

给定一个无向图G=(V,E),多次询问两点之间的最小割。

朴素做法

对于每次询问,我们做一次最大流,复杂度O(QMaxflowTime)Q太大的时候显然无法承受。

这时我们可以先预处理出所有点对的最大流,然后根据每个询问输出答案。

朴素预处理的复杂度O(n2MaxflowTime)n太大的时候我们挂掉了!

提出问题

那么我们如何快速预处理出所有点对的最大流呢?这就是这题所要考察的内容。

按照惯例,我们考虑问题要从简单入手,然后推到一般化。注意图是无向的。

那图的简化是什么?没错,是

那么假设现在有一颗无向树,求所有点对的最大流用 LCA + RMQ 即可解决。(例如:2857—TT 的身体)

那么对于图,我们理所当然想到要去构造一棵等价于原图的最大流树。

Gomory-Hutree 是一颗代表了所有源目节点对间的最小割的树。

求解出 Gomory-Hutree 就可以了解两两节点对之间的最大流(最大流最小割定理)。

举例:一个有6个节点的无向图,节点间的权重皆为1,节点间的最小割如下图所示:

1.png

步骤一:创建一棵星型树,节点1为中心节点,其他节点为叶子节点,如下图左侧所示。

步骤二:分别选编号为26的节点为源节点S,重复做步骤三和步骤四。

步骤三:在星型树中令与S节点相邻的节点为目的节点T,计算ST之间的最大流,并由此得到最小割。

将最大流标注在星型树中S节点与T节点间的链路上。

步骤四:对于每一个编号大于S的节点i,如果在原图中Si是邻居,且iS在同一割集中,则去除星型图中iT的连接,增加iS的连接,如下图中间所示。

2.png

最后可得到如上图右侧所示的 Gomory-Hutree。

算法步骤

  1. 首先任选一个点为根。设以结点1为根,标记1已经 check,把所有的结点都连到根1
  2. 按顺序枚举未 check 的节点T,比如以从小到大的顺序。
    • S为此时结点T的父亲,在原图中求S-T的最大流
    • 从结点S开始 DFS
    • 把在S-T割中属于T侧的未 check 结点设为T结点的儿子;标记T为 check
    • 重复直到所有的点都被 check。注意S-S的最大流为0

时间复杂度

由于1事先被我 check 了,所以我们最后只要 check|V|1次就可以了。

所以复杂度是O((|V|1)MaxflowTime)

预处理所有点对的最大流可以在更新树的同时一起更新,而无需最后再 LCA + RMQ。

模板题