无向图转换为树

Posted

技术标签:

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

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

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

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

【问题讨论】:

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

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

先决条件

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

想法

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

算法

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

    g.v 中的所有顶点最初都标记为未访问,未完成。

    以任意顺序访问所有顶点。跳过标记为“已完成”的节点。 让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

    如果您还没有找到根节点,则您的问题实例不明确: 随意定位剩余的未定向边。

备注

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

    每步骤 2 一次 每步最多两次 2.2.2 每步 2.3 最多一次

    正确性:

    所有包含锐角的边都按照步骤 2.2.1 进行定向

    复杂度(时间):

    访问每个节点: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)

    复杂度(空间):

    O(n) 用于排序(顶点度数不固定)。

    问题可能定义不明确:

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

【讨论】:

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

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

【讨论】:

以上是关于无向图转换为树的主要内容,如果未能解决你的问题,请参考以下文章

算法-图是否为树(并查集或深搜)

求算法,用邻接矩阵和邻接表创建一个图,实现深度和广度搜索,菜单形式,c语言的代码。无向无权的图。

OSMnx 无向图和 (u, v, k) 顺序

❤️数据结构入门❤️(3 - 2)- 无向图割边割点

POJ 3710 无向图简单环树上删边

matlab画无向图,基于坐标的无向图联系作者