【发布时间】:2010-11-23 20:13:21
【问题描述】:
我有一个图表,其中包含未知数量的断开连接的子图。什么是找到它们的好算法(或 Java 库)?
【问题讨论】:
-
谢谢大家,尤其是 MAK 和 Agor。我将从洪水填充和广度优先搜索开始,然后从那里开始。
标签: java algorithm graph disconnected subgraph
我有一个图表,其中包含未知数量的断开连接的子图。什么是找到它们的好算法(或 Java 库)?
【问题讨论】:
标签: java algorithm graph disconnected subgraph
我认为您要查找的内容通常称为Flood Fill。是否通过 BFS 或 DFS 遍历图形取决于您。
基本上,您获取一个未标记(AKA 未着色)节点并为其分配一个新标签。您将相同的标签分配给与该节点相邻的所有节点,依此类推,分配给从该节点可到达的所有节点。
当无法标记更多可达节点时,您可以通过选择另一个未标记节点重新开始。请注意,这个新节点未标记这一事实意味着它无法从我们之前的节点访问,因此位于另一个断开连接的组件中。
当没有更多未标记的节点时,您必须使用的不同标签的数量就是图形的组件数。每个节点的标签告诉您哪个节点是哪个组件的一部分。
【讨论】:
不是 Java 实现,但可能对某人有用,以下是如何在 Python 中实现:
import networkx as nx
g = nx.Graph()
# add nodes/edges to graph
d = list(nx.connected_components(g))
# d contains disconnected subgraphs
# d[0] contains the biggest subgraph
更多信息here。
【讨论】:
这个问题有很多方面没有得到充分解释,所以我将给出一个有点详尽的答案。尽管我倾向于发布文字墙。 :/ 另请注意,我假设这是一个家庭作业问题或自学问题,所以我不会直接给出答案。
检测图连通性的两种基本算法是Depth First Search 和Breadth First Search。这些确实是您要查看的两个起点。两者都会让你找到解决方案,但方式不同,如果不考虑问题的一些非常深入的方面,很难争论哪个“更好”。但让我们继续前进。
正如我之前提到的,你遗漏了一些重要的细节,我将在这里谈一些可能性。
你的图是有向图还是无向图?您是否考虑“强”意义上的连通性(在这种情况下,请参阅 oggy 的回答),还是“弱”意义上的连通性?根据您的答案,您将不得不以一种稍微不同的方式来处理您的算法。请注意,对于无向图,弱连接和强连接是等价的,这很好。但无论如何,在实施或寻找算法时,您都必须牢记图表的结构。
此外,还有一个问题是“找到子图”(释义)是什么意思。通常图连接是一个决策问题——简单地说“有一个连接的图”或“有两个或多个子图(又名,它是断开的)”。拥有一个算法需要最少的工作量,这很好。 :) 下一步将是图表的count,字面意思是它们的数量,而且书本也不是那么糟糕。倒数第二,您可能需要每个子图中的节点列表。最后,您可能希望逐字复制出子图、边和所有(因此返回类型将是图的列表,我想,其中每个图都是连接的隐含不变量)。这些不同的结果类型都不需要不同的算法,但肯定需要不同的方法来处理书本。
对于一个非常基本的问题来说,所有这些似乎都是一种荒谬的矫枉过正,但我想我只想强调即使是这样一个简单的图形问题所涉及的所有方面。作为一种悬念,请注意这些甚至都没有涉及运行时或内存使用! :) - 阿戈尔
【讨论】:
我假设您想找到所有(强)连接的组件?为此,您可以使用Tarjan's algorithm(DFS 的一种变体)
【讨论】:
如何使用广度优先搜索来查找所有连接的节点?获得连接节点列表后,从所有节点列表中减去该列表。您最终会得到一个断开连接的节点列表
【讨论】: