我正在尝试解决图形问题(这不是为了做作业,只是为了练习我的技能)。给出了DAG ,其中V是顶点集合,E是边线。该图被表示为邻接表,所以甲v是包含的所有连接的一组v。我的任务是找到它的顶点是从每个顶点可达v ∈ V。我使用的解决方案的复杂度为 O (V 3),带有传递闭包,但是我在博客中读到它可以更快,尽管它没有揭示如何实现。谁能告诉我另一种方法(具有更好的复杂性)来解决DAG中的传递闭包问题?
我正在尝试解决图形问题(这不是为了做作业,只是为了练习我的技能)。给出了DAG ,其中V是顶点集合,E是边线。该图被表示为邻接表,所以甲v是包含的所有连接的一组v。我的任务是找到它的顶点是从每个顶点可达v ∈ V。我使用的解决方案的复杂度为 O (V 3),带有传递闭包,但是我在博客中读到它可以更快,尽管它没有揭示如何实现。谁能告诉我另一种方法(具有更好的复杂性)来解决DAG中的传递闭包问题?
Answers:
我们的图是非循环的这一事实使这个问题更加简单。
拓扑排序可以使我们对顶点进行排序,使得如果i < j,则从v j到v i的边将不存在。我们已经列出了顶点,以便所有边都在列表中“向前”。
(编辑以修复分析并提供更快的算法)
现在,我们从最后一个顶点开始向后浏览该列表。v n的传递闭包本身。还要加上v n到每个具有边的顶点的传递闭合中。
对于彼此的顶点,从末尾开始,首先将v i添加到其自己的传递闭包中,然后将所有内容添加到vi i的传递闭包中的传递闭包中的所有内容添加到边缘为的所有顶点的传递闭包中。
运行时间在最坏的情况下,与Ñ顶点和的数目米∈ ø (Ñ 2)的边缘的数目。拓扑排序需要时间O (n + m )。然后,我们在向后遍历中进行另一个O (m n )工作:当我们向后遍历列表时,对于每个边,我们必须相加n 顶点到某人的及物关闭。
请注意,通过用位数组表示每个人的传递闭包,可以得到很好的恒定因子加速。假设您只有;那么您将使用单个64位int,如果i在我的传递闭包中,则位i为1,否则为0。然后,我们将i的传递闭包中的所有内容添加到j的那部分很快:我们只取c j | = 。(二进制或运算。)
对于 ,您必须将它们保留在数组中并进行一些算术运算,但是它比Object集要快得多。
另外,我知道在最坏的情况下,大仍为O (n 3,但是要在实践中击败它,您必须要复杂得多。该算法在稀疏图上也表现出色。