【问题标题】:Identifying largest connected component in a matrix识别矩阵中最大的连通分量
【发布时间】:2015-04-23 19:08:17
【问题描述】:

我有一个带有 1 和 0 的 python numpy 矩阵,我需要确定矩阵中 1 的最大“集合”: http://imgur.com/4JPZufS

矩阵最多可以有 960.000 个元素,所以我想避免暴力解决方案。

解决这个问题最聪明的方法是什么?

【问题讨论】:

  • 你已经尝试过了吗?分享一下你目前所拥有的怎么样?
  • 我有一个实现,我将矩阵划分为子矩阵,然后我将这些子矩阵的总和找到最大的一个,我这样做两次,然后我通过检查相邻的强力解决方案字段并将组件添加到集群中
  • 如果您不需要自己的实现(例如,如果是家庭作业),请查看 NetworkX 的 python 模块 (networkx.github.io) 和相关问题:stackoverflow.com/questions/24374627/…
  • 谢谢。会去看看!

标签: python algorithm matrix depth-first-search connected-components


【解决方案1】:

您可以使用名为disjoint-set 的数据结构(here 是python 实现)。这种数据结构就是为这类任务而设计的。

如果当前元素为 1,则迭代行,检查是否有任何已遍历的邻居为 1。如果是,则将此元素添加到其集合中。如果这些集合有超过 1 个联合。如果没有邻居是 1,则创建一个新集合。最后输出最大的集合。

这将按如下方式工作:

def MakeSet(x):
  x.parent = x
  x.rank   = 0
  x.size = 1

def Union(x, y):
  xRoot = Find(x)
  yRoot = Find(y)
  if xRoot.rank > yRoot.rank:
    yRoot.parent = xRoot
  elif xRoot.rank < yRoot.rank:
    xRoot.parent = yRoot
  elif xRoot != yRoot: # Unless x and y are already in same set, merge them
    yRoot.parent = xRoot
    xRoot.rank = xRoot.rank + 1
  x.size += y.size
  y.size = x.size

def Find(x):
  if x.parent == x:
    return x
  else:
    x.parent = Find(x.parent)
    return x.parent

""""""""""""""""""""""""""""""""""""""""""

class Node:
  def __init__ (self, label):
    self.label = label
  def __str__(self):
    return self.label

rows = [[1, 0, 0], [1, 1, 0], [1, 0, 0]]
setDict = {}
for i, row in enumerate(rows):
  for j, val in enumerate(row):
    if row[j] == 0:
      continue
    node = Node((i, j))
    MakeSet(node)
    if i > 0:
      if rows[i-1][j] == 1:
        disjointSet = setDict[(i-1, j)]
        Union(disjointSet, node)
    if j > 0:
      if row[j-1] == 1:
      disjointSet = setDict[(i, j-1)]
      Union(disjointSet, node)
    setDict[(i, j)] = node
print max([l.size for l in setDict.values()])

>> 4

这是一个完整的工作示例,其中不相交集的代码取自上面的链接。

【讨论】:

  • 实际上,如果您提前知道边缘,那么不相交集有点过分了。你可以只做一个图遍历
【解决方案2】:

我认为provided answer 中的计数将关闭。例如。如果将 rows 更改为 rows = [[1, 0, 0], [1, 1, 1], [1, 0, 0]] 仍然得到 4,尽管它应该是 5。将 Union 更改为

def Union(x, y):
  xRoot = Find(x)
  yRoot = Find(y)
  if xRoot.rank > yRoot.rank:
    yRoot.parent = xRoot
    xRoot.size += yRoot.size
  elif xRoot.rank < yRoot.rank:
    xRoot.parent = yRoot
    yRoot.size += xRoot.size
  elif xRoot != yRoot:  # Unless x and y are already in same set, merge them
    yRoot.parent = xRoot
    xRoot.rank = xRoot.rank + 1
    xRoot.size += yRoot.size

似乎解决了。

【讨论】:

    猜你喜欢
    • 2012-05-10
    • 2018-08-30
    • 2021-11-17
    • 2019-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    相关资源
    最近更新 更多