我有这个算法来查找有向图是否具有唯一的拓扑顺序
最后,我在L中有顶点的拓扑顺序。如果我可以在步骤2中选择多个顶点,那么这个拓扑顺序不是唯一的。如果我在图表为空之前遇到任何这些步骤,则意味着该图表根本没有拓扑顺序。
我认为这个算法的时间复杂度是O(n),其中n是图中顶点的数量,但显然这是不对的。
答案 0 :(得分:1)
让m
为边数,n
为顶点数。您的算法的简单实现是O(nm)
。如果通过遍历可以执行O(m)
次循环的n
迭代的边集来实现步骤2。
但是,您可以按照以下时间复杂度O(n+m)
执行此操作。我将假设一个顶点存储为一个整数,一个边存储为一对尾部和头部的整数。
步骤A
除了L
之外,请初始化以下内容
(a)一个数组A
,每个顶点有一个插槽。数组应为每个顶点i
存储一个指向i
的所有顶点的列表。
(b)汇总S
个汇点(因此可以删除)。
(c)数组B
,每个顶点也有一个插槽。此数组应存储每个顶点i
数的边缘远离 i
。当此数字降至零时,相应的顶点必须是接收器,因此可以添加到S
。
步骤B
首先迭代一组边。将每个边E: i -> j
增加B[i]
一个,并将E
添加到列表A[j]
。此迭代为O(m)
。
第C步
迭代数组B
,如果B[i] == 0
,请将i
添加到堆栈S
。这是O(m)
。
步骤D
步骤D是一个while循环
while (S is not empty) {
从i
移除第一个接收器S
并将其添加到L
。因为您有一个列表A[i]
,所以您知道指向i
的所有边。对于这些边缘中的每一个E: j-> i
,通过从1
中减去B[j]
来删除边缘。如果B[j]
的值已降至零,请将j
添加到S
}.
在步骤D结束时,所有接收器都将被移除。步骤D为O(n+m)
,因为每个顶点最多被移除一次,每条边最多读取一次。
答案 1 :(得分:0)
没有指定数据结构,但选择好,运行时间为O(m + n),其中m是边数,n是顶点数。对于密集图,可能是m>> n,所以O(n)时间不足以读取整个图表。相反,如果图形断开,则可能是n>> m,所以大O内的两个术语都是必要的。