【问题标题】:Undirected graph conversion to tree无向图转换为树
【发布时间】:2011-12-22 22:40:52
【问题描述】:

给定一个undirected graph,其中每个节点在空间中都有一个笛卡尔坐标,具有树的一般形状,是否有算法将图形转换为树,并找到合适的根节点?

请注意,我们对“树”的定义要求分支不能以锐角偏离父节点。

请参阅下面的示例图。我们如何找到红色节点?

【问题讨论】:

  • 在这个例子中的无向图中,任何节点都可以作为根,你会得到一棵合适的树。如果我做对了,哪个节点将成为根取决于节点的空间排列。但我不清楚如何,以及“分支不会以锐角偏离父节点”的意思。你能澄清一下吗?你能解释一下吗?为什么最上面或最右边的节点不能成为您的应用程序的根?
  • @paniwani:您的意思是说,将兄弟姐妹链接到其(公共)父节点的分支之间的角度一定不是锐角吗?除了坐标和图形结构之外,您还有什么数据结构可以处理吗?除了根节点的度数,你的树是二元的吗?二叉树会更容易处理,因为相邻边之间的 3 个角度中恰好有 1 个是锐角,因此可以在本地确定父/子关系。
  • @paniwani:请注意,您的问题似乎定义不明确:考虑任何 steiner 树;分支之间根本没有没有锐角。因此任何节点都可以被选为根节点而不会违反您的约束
  • 不能每个节点都是树的根,这取决于您如何看待图表?

标签: graph tree graph-theory nodes


【解决方案1】:

这里是关于如何解决您的问题的建议。

先决条件

  • 符号:
    • g 图,g.v 图顶点
    • v,w,z:单个顶点
    • e: 个人优势
    • n: 顶点数
  • 无向树 g 和给定节点 g.v 的任何组合唯一地确定具有根 g.v 的有向树(可通过归纳证明)

想法

  • 通过g 隐含的有向树中的方向补足g 的边,并通过g 节点处的局部计算补足尚未找到的根节点。
  • 这些方向将代表节点之间的子父关系(v -> wv 子,w 父)。
  • 完全标记的树将包含一个出度为 0 的唯一节点,这是所需的根节点。您最终可能会得到 0 个或多个根节点。

算法

假定图/树结构的标准表示(例如邻接表)

  1. g.v 中的所有顶点最初都标记为未访问,未完成。
  2. 以任意顺序访问所有顶点。跳过标记为“已完成”的节点。
    v 成为当前访问的顶点。

    • 2.1 从一个随机选择的e_0 开始顺时针扫过链接v 的所有边,按照边与e_0 的角度顺序排列。
    • 2.2。定向相邻的边缘e_1=(v,w_1), e_2(v,w_2),它们包围一个锐角。
      相邻:wrt 根据它们与e_0 包围的角度进行排序。

      [注意:不能保证这样一对的存在,请参阅第二条评论和最后一条评论。如果没有锐角,则从 2. 处理下一个节点。 ]

      • 2.2.1 边e_1, e_2 的方向是已知的:

        • w_1 -> v -> w_2: 不可能,因为祖父子段会包围一个锐角
        • w_1 <- v <- w_2:不可能,同理
        • w_1 <- v -> w_2:不可能,树中没有出度>1的节点

        • w_1 -> v <- w_2:
          只有可能的一对方向。 e_1, e_2 之前可能已经定位。如果先前的方向违反了当前的分配,则问题实例没有解决方案。

      • 2.2.2 此分配意味着子图上的树结构由在不包含e_1 (e_2`的路径上可从w_1 (w_2) 到达的所有顶点诱导。将两个诱导子树中的所有顶点标记为已完成

        [注意:子树结构可能违反角度约束。在这种情况下,问题没有解决方案。 ]

    • 2.3 标记v 已访问。在顶点 v 完成步骤 2.2 后,检查尚未分配方向的连接边的数量 nc

      • nc = 0:这是您一直在寻找的根目录 - 但您必须检查解决方案是否与您的约束兼容。
      • nc = 1:让这条边为(v,z)
        这条边的方向是 v->z,就像你在树上一样。将 v 标记为已完成。

        • 2.3.1 检查z是否标记为完成。 如果不是,请检查连接z 的无向边的数量nc2nc2 = 1:重复步骤 2.3,将 z 替换为 v
  3. 如果您还没有找到根节点,则您的问题实例不明确: 随意定位剩余的未定向边。

备注

  1. 终止: 每个节点最多访问 4 次:

    • 每步骤 2 一次
    • 每步最多两次 2.2.2
    • 每步 2.3 最多一次
  2. 正确性:

    • 所有包含锐角的边都按照步骤 2.2.1 进行定向
  3. 复杂度(时间):

    • 访问每个节点:O(n);
    • 顺时针扫过连接给定顶点的所有边需要对这些边进行排序。
      因此,您需要O( sum_i=1..m ( k_i * lg k_i ) ) 在约束sum_i=1..m k_i = n 下的m <= n 顶点。

      总的来说,这需要O ( n * lg n),因为sum_i=1..m ( k_i * lg k_i ) <= n * lg n 给定sum_i=1..m k_i = n 对于任何m <= n(可通过应用拉格朗日优化来证明)。

      [注意:如果你的树的度数以常数为界,理论上你在每个受影响的节点上以常数时间排序;在这种情况下总计:O(n) ]

    • 子树标记:
      如果实现为 dfs,则此过程最多访问图中的每个节点 2 次。因此总共有O(n) 用于调用此子例程。

      总计:O(n * lg n)

  4. 复杂度(空间):

    • O(n) 用于排序(顶点度数不固定)。
  5. 问题可能定义不明确:

    • 多种解决方案:例如斯坦纳树
    • 没有解决方案:例如图形形状像一个双尖箭头 ()

【讨论】:

  • 该死的..我一直在寻找与 OP 的问题相反的问题,但这很准确。很好解释,有据可查。很好的答案。 (旧帖,我知道)
【解决方案2】:

一个简单的解决方案是围绕红色节点或节点中心定义一个二维矩形,并使用摩尔曲线计算每个节点。摩尔曲线是一种空间填充曲线,更多的是希尔伯特曲线的特殊版本,其中起点和终点相同,坐标位于二维矩形的中间。一般来说,您的问题看起来像一个离散的寻址空间问题。

【讨论】:

    猜你喜欢
    • 2011-09-17
    • 1970-01-01
    • 2017-01-13
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多