在动态图上维护连接的组件信息的最有效的算法和数据结构是什么?


9

假设我有一个无向的有限稀疏图,并且需要能够有效地运行以下查询:

  • IsConnected(N1,N2) - 如果在和之间存在路径,则返回,否则返回N 1 N 2 FTN1N2F
  • ConnectedNodes(N) -返回从可访问的节点集N

通过预先计算图形的连接组件,可以轻松完成此操作。这两个查询都可以在时间中运行。O(1)

如果还需要能够任意添加边 -那么我可以将组件存储在不相交的数据结构中。每当添加一条边时,如果它连接了不同组件中的两个节点,我将合并这些组件。这会将成本增加到,将成本增加到和(也可能是)。AddEdge(N1,N2)d d é d ë ø Ñ v Ë ř 小号Ë Ç ķ é ř 一个Ñ Ñ | Ñ ø d ë 小号|小号Ç Ò Ñ Ñ Ê Ç ë d ç Ò ñ ñ Ê ç Ë d ñ ÒO(1)AddEdgeO(InverseAckermann(|Nodes|))IsConnectedÔ 1 ConnectedNodesO(1)

如果我还需要能够任意删除边缘,那么处理这种情况的最佳数据结构是什么?是已知的吗?总而言之,它应该有效地支持以下操作:

  • IsConnected(N1,N2) -返回如果存在之间的路径和,否则。N 1 N 2 FTN1N2F
  • ConnectedNodes(N) -返回可从访问的节点集。N
  • AddEdge(N1,N2) -在两个节点之间添加一条边。请注意,以前可能不存在,或两者都不存在。N 2N1N2
  • RemoveEdge(N1,N2) -删除两个节点之间的现有边缘。

(我从游戏开发的角度对此感兴趣-这个问题似乎在很多情况下都会发生。也许玩家可以建造电力线,我们需要知道发电机是否已连接到建筑物。也许玩家可以锁定并打开门,我们需要知道敌人是否可以到达玩家。但这是一个非常普遍的问题,因此我将其表述为


Ô 1 ñ Ω Ñ Ç Ò Ñ Ñ Ê Ç Ë d Ñ ö d Ë 小号ConnectedNodes不可能在运行,因为如果它返回节点的列表,则需要时间。使用BFS 实现是最佳选择,因此潜在的数据结构仅需要支持IsConnected,AddEdge和RemoveEdge。这似乎是有关你的问题:stackoverflow.com/questions/7241151/...O(1)nΩ(n)ConnectedNodes
汤姆·范德Zanden

@TomvanderZanden返回一个已经建立的集合(在编程中,一个指针或引用)是 ...尽管的用户可以做的事情并不多,但是没有。C o n n e c t e d N o d e s O 1 O(1)ConnectedNodesO(1)IsConnected
user253751

Answers:


11

这个问题被称为动态连接,它是理论计算机科学界的一个活跃的研究领域。仍然有一些重要的问题在这里。

为了弄清楚术语,您需要完全动态的连接, 因为您要添加和删除边。Holm,de Lichtenberg和Thorup(J.ACM 2001)的结果是获得更新时间和查询时间。据我了解,这似乎是可以实现的。简而言之,数据结构保持了生成树的层次结构-并且树中的动态连接更容易覆盖。我可以推荐Erik D. Demaine的笔记,以得到很好的解释,请参阅此处的视频。埃里克(Erik)的笔记还包含其他相关结果的指针。注意:所有这些结果均为理论结果。O log n / log log n O(log2n)O(logn/loglogn)

这些数据结构本身可能不提供ConnectedNodes查询,但是很容易实现。只需维护图形(作为双重连接的边缘列表)作为附加的数据结构,然后进行深度优先搜索以获取可以从某个节点到达的节点。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.