最小割树

lolifamily

注意!

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

题目大意

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

朴素做法

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

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

朴素预处理的复杂度𝑂(𝑛2MaxflowTime)𝑛太大的时候我们挂掉了!

提出问题

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

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

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

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

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

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

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

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

1.png

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

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

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

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

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

2.png

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

算法步骤

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

时间复杂度

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

所以复杂度是𝑂((|𝑉|1)MaxflowTime)

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

模板题