一棵树的线性时间标记算法?


12

我有一棵无向的树,我要标记其顶点。叶节点应标记为一个。然后,假设叶子被去除了。在剩下的树中,叶子应标记为两片。该过程将以显而易见的方式继续进行,直到所有顶点都具有标签为止。我这样做的原因是我想将顶点存储在队列中,并“先离开”浏览它们。有没有简单的方法可以执行此时间?O(n+m)

我可以通过在每个步骤上进行BFS来解决该问题。但是在最坏的情况下,在我经过每个顶点的每一步中,都精确地移去两片叶子并将它们排队。我相信这需要二次时间。

另一个想法是首先找到所有叶子,然后对每个叶子进行BFS。这没有给我想要的解决方案。例如,考虑下图所示的一种“皇冠图”。显示了所需的解决方案,但是从每个叶子启动BFS只会导致使用两个标签。

在此处输入图片说明

理想地,线性时间算法也将易于解释和实现。

Answers:


8

无根树木

您可以使用优先级队列在解决此问题:O(E+VlogV)

  • 将所有顶点放在优先级队列中,其优先级是其度。
  • 当队列为非空时:
    • 删除最低优先级的顶点,该顶点必须为(或最后为)。1 0v10
    • 令,其中遍历所有原始邻居。σ(v)=1+maxσ(u)uv
    • 从的唯一剩余邻居(如果有)的优先级中减去。1u

实际上,我们实际上并不需要优先级队列,并且可以使用时间为的简单队列来实现此算法:O(E+V)

  • 使用所有顶点的度数初始化长度为的数组。V
  • 用“ alive” 初始化另一个长度为数组。V
  • 遍历第一个数组一次,并将所有度顶点推入队列。1
  • 当队列为非空时:
    • 弹出一个顶点。v
    • 令,其中遍历所有原始邻居。σ(v)=1+maxσ(u)uv
    • 将标记为“死”。v
    • 如果具有一些“活动的”邻居,则从的度数中减去。vu1u
    • 如果的新度为,则将推入队列。u1u

植树

请改用DFS。这是该算法的示意图。

  • 给定节点,如果是叶子,则设置。vvd(v)=1
  • 如果不是叶子,则对其所有子代运行该算法,然后令,其中遍历所有子代的集合。vd(v)=1+maxd(u)u

您在根上运行此算法。


这是正确的吗?考虑树1-> 2-> 3-> 4-> 5,其中1是根。2应该得到标签1,但是您给3?还是孩子,您指的是邻居?我们从哪个节点开始dfs?
Knoothe

我的实现是“一举成名”,但是根据您的描述,应该获得标签,因为您必须先删除,然后,然后,然后才能成为叶子。245432
Yuval Filmus 2013年

我没有问这个问题:-)。我将问题解释为:无向树。标记所有叶子。删除它们。递归到结果树上。在这种情况下,树实际上是1-2-3-4-5,在步骤1中,删除1和5,然后删除2和4,然后删除3。请参见有关“皇冠图”的段落。这是找到树中心的经典算法之一。
Knoothe

1不是叶子。它离叶子很远,它是根。我认为这个问题是针对有根的树木。也许我们应该等待OP做出回应。
Yuval Filmus 2013年

2
@YuvalFilmus,只丢2美分,不是吗?叶子为,如果删除它们,则新叶子应为,因此这是在顶点成为叶子之前必须删除多少层的一种度量。如果设置为min,则与叶子相邻的任何顶点都将变为2,但是当删除叶子时它可能不会成为叶子。那句话里面有太多的叶子。我需要一把扫帚。1+max{d(u)}12
卢克·马蒂森

2

一个简单的答案如下:

  • 将其变为有向图,在该图中我们从每个节点到其父都有一条边。请注意,您将获得一个dag(有向无环图)。(u,v)uv

  • 对图进行拓扑排序。

  • 按排序顺序扫描顶点。用比其前代标签中最大的标签多一个标签。由于我们按拓扑顺序进行扫描,因此在尝试标记之前,所有前身都已经获得了标签。vv

每个步骤都可以在时间内完成,因此总运行时间为。我仅在您觉得从概念上比Yuval的答案更容易理解的情况下提及这种替代方法。O(n+m)O(n+m)

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.