代码之家  ›  专栏  ›  技术社区  ›  foobarfuzzbizz

我可以对这个DAG应用什么算法?

  •  4
  • foobarfuzzbizz  · 技术社区  · 15 年前

    我有一个DAG代表一个属性列表。这些属性是这样的:如果a>b,则a具有指向b的边。它也是可传递的,因此如果a>b和b>c,则a具有指向c的边。

    但是,A到C的有向边是多余的,因为A有一个到B的有向边,B有一个到C的有向边。如何修剪所有这些多余边?我在考虑使用最小生成树算法,但我不确定在这种情况下应用哪种算法是合适的

    我想我可以对每个节点及其所有出站边缘进行深度优先搜索,并比较它是否可以在不使用某些边缘的情况下到达某些节点,但这似乎效率低下且速度慢得可怕。

    算法完成后,输出将是所有节点的线性列表,其顺序与图一致。因此,如果a有三条指向b、c和d的定向边,b和c也都有一条指向d的定向边,则输出可以是a b c d或a c b d。

    3 回复  |  直到 10 年前
        1
  •  6
  •   Michel Schinz paulsm4    10 年前

    这叫做 transitive reduction problem . 正式地说,您要寻找一个最小(最小边)有向图,其传递闭包等于输入图的传递闭包。(上面维基百科链接上的图表说明了这一点。)

    显然,存在一种有效的算法来解决这个问题,它与生成传递闭包的时间相同(即,添加传递链接而不是删除链接的更常见的逆问题),但是 link to the 1972 paper 通过aho,Garey和Ullman的下载成本是25美元,一些快速的谷歌搜索没有找到任何好的描述。

    编辑: Scott Cotton's graphlib 包含一个 Java implementation ! 这个Java库看起来组织得很好。

        2
  •  2
  •   foobarfuzzbizz    15 年前

    实际上,在多看了一眼之后,我认为 Topologicalsort 是我真正想要的。

        3
  •  0
  •   Sam Liao    15 年前

    如果这些节点已经是n个具有定向边的节点:

    1. 从任意点m开始,循环其所有子边,选择最大的子边(如n),删除其他边,复杂度应为o(n)。如果不存在n(没有子边,请转到步骤3)。
    2. 从N开始,重复步骤1。
    3. 从M点开始,选择最小的父节点(如T),移除其他节点的边。
    4. 从t开始,重复步骤3…..

    实际上,它只是一个排序算法,并且总的复杂性应该是O(0.5N^2)。


    一个问题是,如果我们想要循环一个节点的父节点,那么我们需要更多的内存来记录边缘,这样我们就可以从子节点追溯到父节点。这可以在步骤3中得到改进,我们从大于m的左侧节点中选择一个节点,这意味着我们需要保留一个节点列表,以了解剩下的节点。