algorithm - 网络流算法

标签 algorithm

我遇到了这样的问题:

我们有一个二分图。例如

A1 B1
A2 B2
A3 B3
A4

这是邻接列表表示(假设图是双向的)

B1 -> A2, A3
B2 -> A2, A3, A4
B3 -> A1

最终结果应该是左侧 (As) 的所有节点恰好有 1 个传入边,同时 - 我们需要最小化需要从各个 Bs 节点出去的边的最大数量。在这种情况下,答案是:

B3 can connect to A1
B2 can connect to A2, A4
B1 can connect to A3

所以这里需要从单个 Bs 节点出去的边的最大数量是 2。我们不能覆盖所有 A,同时让一个 B 节点没有 2 条从它出去的边来覆盖 As。

另一个例子:

A1 B1
A2 B2
A3 B3
A4 B4

B1 -> A1, A2, A3
B2 -> A1, A2, A3, A4
B3 -> A1, A2, A3
B4 -> A1, A2, A3

在这种情况下,答案是:

B1 can connect to A1
B2 can connect to A4
B3 can connect to A3
B2 can connect to A2

这样,我们将一次覆盖所有 A,同时我们最小化了需要从各个 B 中伸出的边的最大数量。所以这里单个Bs节点需要出的边的最大数量是1。

另一个例子:

A1 B1
A2 B2
A3 B3
A4
A5
A6

B1 -> A6
B2 -> A1, A2, A3, A4, A5
B3 -> 

在这种情况下,答案是 5,即需要从单个 B 出去的边的最大数量是 5。不能少于这个数量。

我已经实现了基本的福特富尔克森算法,我知道这也是网络流,但不知道如何与之关联。

如果有人可以提供有关图表的一些提示,那就太好了。

谢谢

最佳答案

找到一个最佳解决方案 - 所有 B 最多有一个出边(如果存在)很简单:

  • 向图中添加源和接收器。源会有一个输出 容量为 1 的边到 B 列表中的所有顶点。
  • 全部 (B,A)边的容量为 1。
  • 所有 A 都有一个到水槽的容量为 1 的外缘。
  • 现在,运行流算法将产生最大数量 A 中的顶点可以被每个只有一个 B 覆盖 出边(最佳解决方案,如果存在)

编辑:

现在,基于上述想法,并且由于您正在尝试最小化从单个 B 到 A 的最大边数(而不是它们的总数,正如我之前所想的那样) ,最优解很简单:

while there is no coverage:
   set capacity(source,b_k) = increase_size() (for each b_k in B)
   run max flow algorithm on the graph suggested above
return last flow found

复杂度为O(E*V*#iterations) (在此问题中 f <= V ,因此 ford-fulkerson 的复杂度为 O(EV) ),其中 #iterations可以在您寻求的最小最大数中线性完成,或者使用指数增加,然后在范围上进行二分搜索(如 Evkeny Kluev 建议),以该数字的对数。
E=O(V)在二部图中,我们总共得到 O(V^2*log(V))

关于algorithm - 网络流算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12687664/

相关文章:

python - 将具有互元素的所有子数组合并为一个子数组

查找最短路径数的算法

algorithm - QuickSort 的迭代实现中的无限循环?

algorithm - 使用顺时针方向绕 x 轴旋转立方体

c++ - 将粒子排列成矩形

algorithm - 无需 T9 即可计算键盘序列可能单词的高效算法

algorithm - AES 算法在纯文本和字节序列上的工作方式是否相同?

java - 为什么我的快速排序性能比合并排序差?

algorithm - 子串搜索

c++ - 如何从根中有效地找到多项式的系数?