如何实现需要有效收缩和扩展连接组件的图算法?

时间:2018-04-01 11:40:23

标签: algorithm data-structures graph-theory

有些算法,如Edmond's AlgorithmBoruvka's Algorithm,需要程序员创建一个图表,该图表是通过将某些节点收缩到一个节点中获得的,然后再将其扩展回来。

收缩的正式描述如下:

G成为顶点为V和边E的图形。让C成为G的关联组件。 G相对于C的收缩被定义为V - nodes(C) + C*上的图表,其中C*是"超级节点"代表签约的组成部分。不涉及C中的顶点的边是原样的。 C中具有端点的边缘现在已连接到C*

For example, an intermediate step in Edmond's Algorithm might require contracting a cycle, operating on the contracted graph, and then expanding it back again

我不清楚如何使用邻接列表等表示来实现这样的算法原语。

什么是一种优雅而有效的方式来表示图表,以便他们可以签约,同时记住相关数据以扩展它们?

2 个答案:

答案 0 :(得分:3)

我会使用 disjoint-set 数据结构,也称为 union-find 数据结构。想象一下,每个顶点最初都是一个集合。现在工作是这样的:

对于收缩:获取参与所有收缩的所有顶点的并集。集合中的所有顶点都由称为所有顶点的父节点的单个顶点表示,您可以将其称为超级节点。该链接包含有关如何执行此操作的所有详细信息。

对于扩展,只需反过来,在最坏的情况下,您必须使每个顶点代表一个集合。所以基本上这种方法适用于非重叠集合操作。

答案 1 :(得分:3)

首先,我喜欢Sumeet Singh的回答,你可以先探索一下。我有类似的想法,但细节略有不同。

不幸的是,我现在不在一个可以绘制图表的地方,这在这里真的很有帮助。让我试着清楚地描述我的想法。

解决方案涉及创建两种新类型的节点:

  • a"超级节点"代表合同集
  • a"转发节点"是超级节点的代理,它知道如何撤消"它的创造。
  • 转发节点有三个引用:它的超级节点,它的"外部"节点,以及它的内部"节点
  • 超级节点有一个包含所有转发节点的列表。

收缩:

考虑您的连接组件G.

  • 创建一个"超级节点"表示此连接组件。

  • 对于G中的每个节点,可能有边连接到G中的节点而不是。调用那些边e1,e2,e3,...

    < / LI>
  • 为每个边创建转发节点F1,F2,F3 ....

  • 现在对于每个边缘,假设e1是从A1(不在G中)到B1(在G中)。从图表中移除A1-B1边缘,添加A1-F1边缘。 A1成为F1的外部节点,B1成为F1的内部节点。

扩张正好相反:

  • 对于超级节点中的每个转发节点F,从外部节点移除边缘,将外部节点的边缘添加回内部节点,并删除所有转发节点。

  • 删除超级节目

实现图形操作时会遇到棘手的问题。如果你问&#34;你的邻居是什么&#34;转发节点必须将该请求转发给超级节点,并且超级节点必须说出所有转发节点的所有外部节点&#34;。等等。