有些算法,如Edmond's Algorithm或Boruvka's Algorithm,需要程序员创建一个图表,该图表是通过将某些节点收缩到一个节点中获得的,然后再将其扩展回来。
收缩的正式描述如下:
让G
成为顶点为V
和边E
的图形。让C
成为G
的关联组件。 G
相对于C
的收缩被定义为V - nodes(C) + C*
上的图表,其中C*
是"超级节点"代表签约的组成部分。不涉及C
中的顶点的边是原样的。 C
中具有端点的边缘现在已连接到C*
。
我不清楚如何使用邻接列表等表示来实现这样的算法原语。
什么是一种优雅而有效的方式来表示图表,以便他们可以签约,同时记住相关数据以扩展它们?
答案 0 :(得分:3)
我会使用 disjoint-set 数据结构,也称为 union-find 数据结构。想象一下,每个顶点最初都是一个集合。现在工作是这样的:
对于收缩:获取参与所有收缩的所有顶点的并集。集合中的所有顶点都由称为所有顶点的父节点的单个顶点表示,您可以将其称为超级节点。该链接包含有关如何执行此操作的所有详细信息。
对于扩展,只需反过来,在最坏的情况下,您必须使每个顶点代表一个集合。所以基本上这种方法适用于非重叠集合操作。
答案 1 :(得分:3)
首先,我喜欢Sumeet Singh的回答,你可以先探索一下。我有类似的想法,但细节略有不同。
不幸的是,我现在不在一个可以绘制图表的地方,这在这里真的很有帮助。让我试着清楚地描述我的想法。
解决方案涉及创建两种新类型的节点:
收缩:
考虑您的连接组件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;。等等。