如何将无向图转换为DAG?

时间:2011-11-14 20:51:22

标签: algorithm graph-theory graph-algorithm

Wiki page

  

任何无向图都可以通过选择其顶点的总顺序并将每个边缘从顺序中的早期端点定向到后一个端点而成为DAG。

但我不知道如何获得无向图的总顺序。我应该使用DFS吗?如果是这样,我将如何进行?

更多信息:我正在开发一个无向图,它有一个源和一个接收器。我试图引导这些边缘,以便沿着边缘方向我可以从源头到达接收器。

4 个答案:

答案 0 :(得分:7)

总顺序基本上只是按照某种顺序排列所有顶点 - 将其视为用1到| V(G)|的数字标记每个顶点。这为我们提供了一种一致的方法来知道我们检查的任何顶点对哪个顶点更高。

是的,您可以通过深度优先搜索获得总排序。每次在DFS中探索顶点时,只需为每个顶点指定递增计数器的值。这就是你如何获得总订单。

但是您不需要明确获得总排序的标签来获得DAG。如果我们使用上述探索时间作为我们的排序,那么我们可以按如下方式进行:在进行DFS遍历时定向边缘,将每个无向边指向远离当前正在扩展的顶点。

基本上,我们之前探索过的顶点指向稍后探索过的顶点。

例如。如果你有

  A
 / \
B---C

并且你开始探索A,你会将A上的边缘定位在A远离A:

A --> B
A --> C
B --- C

现在说你在DFS遍历中选择B来探索下一个。然后你将只留下A和B之间的边缘,因为你已经定位了这个边缘(A已经完全展开)。 B和C之间的边缘是未触及的,因此将其定位在远离当前顶点B的位置以获得:

A --> B
A --> C
B --> C

当你探索C时,它的所有邻居都已完全展开,所以C没有什么可做的,并且没有更多的顶点需要探索。

对“更多信息”的回应:

在这种情况下,只需确保首先展开源顶点,然后不要探索接收器。例如。对

A-B-C
|/
D

其中D是源,B是接收器,你可以:展开D,然后是A,然后是C.你会得到:

D --> A
D --> B
A --> B
C --> B

答案 1 :(得分:1)

实际上我认为通过“选择总订单”在维基页面中的含义意味着自己定义总订单。换句话说,如果我们检查最简单的无向图:

A----B

将此无向图转换为DAG显然取决于您是选择在B之前订购A还是在B之后订购A.如果您在B之前选择A,则它变为:

A--->B

否则,它变为:

B--->A

这正是通过“将每个边缘定向”从“EARLIER”端点(总顺序中较早出现的端点)到“LATER”端点的含义。

同样,对于:

    A
   / \
  /   \
 B-----C

如果您将总订单定义为:

B A C

然后有向图应该是这样的:

B->A, B->C, A->C

答案 2 :(得分:1)

问题在于,在我们将无向边变为有向边之后,我们不希望任何循环。

例如,假设我们有完整的三角形图

A -- B
  \  |
   \ |
     C

我们可以选择边缘的方向为A - >; B,B - > C和C - >甲

A -> B
 \\  |
   \ v
     C

但是接下来我们会得到一个循环,而不是定向非循环图。

维基百科页面中建议的技巧是选择顶点的排序,任何排序,实际上,并使用它来确定指向边缘的方向。

由于边缘在顺序中向上指向,我们再也不能“退回”以完成一个循环,因此得到的图形保证是非循环的。

答案 3 :(得分:0)

您可以获得总订单并将无向图转换为反向订单后中的DAG编号节点。

执行订单后深度优先遍历,在您离开时为每个节点分配一个编号,按顺序从1到n。您访问相邻节点的顺序决定了DAG中边的方向。不要遍历从较高编号节点到较低编号节点的边缘 - 这会打破周期,有效地确定在最终DAG中此边缘将处于相反方向。

此顺序给出了图的拓扑排序,它是一个总顺序,由于存在拓扑排序,因此图形变为DAG。

编辑:为了澄清,一旦您使用其RPO编号标记了节点,对于原始图表中的每条边a <-> b,DAG中的边缘为{{1} } iff a -> b,否则边缘为RPO-number(a) < RPO-number (b)

编辑:上面的内容有点矫枉过正,如果某些边缘被指示,它会起作用,如果所有边缘都是无向的,如@missingno指出的那样,任何顺序就足够了。