【问题标题】:Finding all disconnected subgraphs in a graph在图中查找所有断开连接的子图
【发布时间】:2010-11-23 20:13:21
【问题描述】:

我有一个图表,其中包含未知数量的断开连接的子图。什么是找到它们的好算法(或 Java 库)?

【问题讨论】:

  • 谢谢大家,尤其是 MAK 和 Agor。我将从洪水填充和广度优先搜索开始,然后从那里开始。

标签: java algorithm graph disconnected subgraph


【解决方案1】:

我认为您要查找的内容通常称为Flood Fill。是否通过 BFS 或 DFS 遍历图形取决于您。

基本上,您获取一个未标记(AKA 未着色)节点并为其分配一个新标签。您将相同的标签分配给与该节点相邻的所有节点,依此类推,分配给从该节点可到达的所有节点。

当无法标记更多可达节点时,您可以通过选择另一个未标记节点重新开始。请注意,这个新节点未标记这一事实意味着它无法从我们之前的节点访问,因此位于另一个断开连接的组件中。

当没有更多未标记的节点时,您必须使用的不同标签的数量就是图形的组件数。每个节点的标签告诉您哪个节点是哪个组件的一部分。

【讨论】:

  • 谢谢,这是一个很好的起点,也是一个非常实用的答案。
【解决方案2】:

不是 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

【讨论】:

    【解决方案3】:

    这个问题有很多方面没有得到充分解释,所以我将给出一个有点详尽的答案。尽管我倾向于发布文字墙。 :/ 另请注意,我假设这是一个家庭作业问题或自学问题,所以我不会直接给出答案。

    检测图连通性的两种基本算法是Depth First SearchBreadth First Search。这些确实是您要查看的两个起点。两者都会让你找到解决方案,但方式不同,如果不考虑问题的一些非常深入的方面,很难争论哪个“更好”。但让我们继续前进。

    正如我之前提到的,你遗漏了一些重要的细节,我将在这里谈一些可能性。

    你的图是有向图还是无向图?您是否考虑“强”意义上的连通性(在这种情况下,请参阅 oggy 的回答),还是“弱”意义上的连通性?根据您的答案,您将不得不以一种稍微不同的方式来处理您的算法。请注意,对于无向图,弱连接和强连接是等价的,这很好。但无论如何,在实施或寻找算法时,您都必须牢记图表的结构。

    此外,还有一个问题是“找到子图”(释义)是什么意思。通常图连接是一个决策问题——简单地说“有一个连接的图”或“有两个或多个子图(又名,它是断开的)”。拥有一个算法需要最少的工作量,这很好。 :) 下一步将是图表的count,字面意思是它们的数量,而且书本也不是那么糟糕。倒数第二,您可能需要每个子图中的节点列表。最后,您可能希望逐字复制出子图、边和所有(因此返回类型将是图的列表,我想,其中每个图都是连接的隐含不变量)。这些不同的结果类型都不需要不同的算法,但肯定需要不同的方法来处理书本。

    对于一个非常基本的问题来说,所有这些似乎都是一种荒谬的矫枉过正,但我​​想我只想强调即使是这样一个简单的图形问题所涉及的所有方面。作为一种悬念,请注意这些甚至都没有涉及运行时或内存使用! :) - 阿戈尔

    【讨论】:

    • 谢谢,这是一个自我教育问题,我很欣赏细节,我很重视你提出我所做的假设。我正在使用无向图,我的目标是生成一种方法,该方法采用一个图并返回所有子图的集合。
    【解决方案4】:

    JGraphT 是一个很好的开源图形库,获得 LGPL 许可。我过去曾用它来处理图表并检测图表中的循环。它也相当容易使用,您可以使用JGraph 来可视化图表。

    【讨论】:

    • ConnectivityInspector 类应该是需要的。
    • 除了证明循环的存在/不存在之外,我从来不需要做太多事情,所以我不确定,所以我只是链接到库 - 它对我们的项目来说非常可靠。
    【解决方案5】:

    我假设您想找到所有(强)连接的组件?为此,您可以使用Tarjan's algorithm(DFS 的一种变体)

    【讨论】:

      【解决方案6】:

      如何使用广度优先搜索来查找所有连接的节点?获得连接节点列表后,从所有节点列表中减去该列表。您最终会得到一个断开连接的节点列表

      【讨论】:

      • 哇,这正是我所需要的。如果您对特定的子图分割等不感兴趣,这是最快的。唯一的问题是在图中从哪里开始搜索,但这取决于 c 的特定图。
      【解决方案7】:

      我遇到了一个类似的问题,我想要一个有向图的所有弱连接子图。我在博客上写了here。我使用了JUNG API 并比较了两种方法。我的第一种方法可以作为模板来解决您的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-13
        • 1970-01-01
        相关资源
        最近更新 更多