【问题标题】:Finding the root elements of a set of elements/nodes in a multiway tree or a connected graph在多路树或连通图中查找一组元素/节点的根元素
【发布时间】:2019-09-09 08:24:14
【问题描述】:

我在寻找合适的算法来实现以下内容时遇到问题:

我有一组 wifi 链接作为连接图或多路树连接。

我遇到的问题是:当我断开连接时,几个 wifi 节点出现故障,我想知道根本问题是什么是 wifi 节点承载所有其他链接

示例:

  • 节点 1 -> 节点 2、节点 3 和节点 4
  • 节点 2-> 节点 A、B 和 C
  • 节点 3 是叶子
  • 节点 4 -> 节点 D 和 E

如果我有节点 4、D 和 E 宕机,那么我知道根本原因是节点 4

我考虑过使用最小共同祖先,但是,我无法将其适应多路树而不是二叉树

关于如何解决这个问题的任何建议?

【问题讨论】:

  • 这是有向图吗?
  • 在某种意义上说,我们有一个根,我们有一个叶子。但是,我们可以将其视为无向图,因为向下的节点总是在末端,不可能根节点向下而叶子向上
  • 请把你的代码贴到现在,至少我们可以看到数据结构。我还想知道linked-list 标签...您是否使用链表来表示图形?无论如何,包括你的尝试。

标签: python algorithm linked-list graph-theory


【解决方案1】:

您可以使用字典来表示您的wifi网络,然后简单地使用递归查找问题根源:

d = {1: [2, 3, 4], 2: ['A', 'B', 'C'], 3: None, 4: ['D', 'E']}
def search(_d, a):
   return (_d and a in _d) or (_d and any(search(d.get(i, []), a) for i in _d))

down = ['D', 'E', 4]
r = [a for i, a in enumerate(down) if all(search(d.get(a, []), j) for j in down[:i]+down[i+1:])]

输出:

[4]

编辑:如果中断的发起者可能不在 down 中,您可以简单地展平结构并再次运行搜索:

down = ['D', 'E']
_r = {a for c, _d in d.items() for a in [c, *([] if _d is None else _d)]}
result = [i for i in _r if all(search(d.get(i, []), j) for j in down)]

输出:

[1, 4]

输出为[1, 4],因为41 的子节点,而4 包含受影响的子节点。如何区分这些结果取决于您自己,因为两者都可能有效,即 1 可能已关闭或 4 可能已关闭。


根据您的最新输入,我认为最好的方法是创建一个新字典,为集合中的每个父级记录所有子节点。

from collections import defaultdict
def get_paths(_d, c = []):
   for i in _d:
     if d.get(i) is None:
        yield c+[i]
     else:
        yield from get_paths(d[i], c+[i, *([] if d[i] is None else d[i])])

result = defaultdict(list)
for a, b in d.items():
   result[a].extend(([] if b is None else get_paths(b)))

result = {a:{i for c in b for i in c} for a, b in result.items()}

现在,获取下节点:

def get_down(down):
   _r, _n = zip(*[[a, b] for a, b in result.items() if b and all(i in down for i in b)])
   n = {i for b in _n for i in b}
   return list(_r) + [i for i in down if i not in result and i not in n]


final_results = [get_down(i) for i in [['D', 'E','C'], ['D', 'E']]]

输出:

[[4, 'C'], [4]]

【讨论】:

  • 非常有趣的方法。但是,如果只有 D 和 E 关闭,问题很可能来自 4,但它返回一个空字符串,它应该返回 4。我相信我们必须以某种方式进行修改
  • @BusyBee 我建议展平d 以查找所有输入节点,然后遍历展平结果以查找包含受影响子节点的项目。请查看我最近的编辑,因为我添加了解决此问题的潜在方法。
  • 这很好,但是,在这种情况下,4 应该不是 1 的原因,好像 1 有问题,4 也会出现问题。目前,只剩下 1 个问题,如果我们将“C”添加到故障站点,我们现在将有 2 个不同的故障点:“C”和“4”。在上面的代码中,如果down站点是['D', 'E','C'],它会返回[1],但是它应该返回['C',4]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
相关资源
最近更新 更多