【发布时间】:2015-07-04 11:40:37
【问题描述】:
我知道执行此操作的蛮力方法是对图的所有顶点执行 DFS。因此,对于该算法,复杂度为 O(V|V+E|)。但是有没有更有效的方法来做到这一点?
【问题讨论】:
标签: algorithm complexity-theory theory graph-theory
我知道执行此操作的蛮力方法是对图的所有顶点执行 DFS。因此,对于该算法,复杂度为 O(V|V+E|)。但是有没有更有效的方法来做到这一点?
【问题讨论】:
标签: algorithm complexity-theory theory graph-theory
我从http://research.microsoft.com/pubs/144985/todsfinal.pdf 之类的论文中得到的印象是,在一般情况下,没有比O(VE) 或O(V^3) 更好的算法。对于稀疏图和其他特殊图,有更快的算法。但是,如果您对将对数据进行的查询数量有所了解,您似乎仍然可以通过将“索引构造”与“查询”分开来进行改进。如果要进行大量查询,则O(1) 可以用于查询,前提是所有数据都已预先计算(DFS 或 Floyd-Warshall 等)并存储在O(n^2) 空间中。另一方面,如果查询相对较少,则可以以牺牲查询时间为代价来减少空间和/或索引构建时间。
【讨论】:
[编辑:正如 kraskevich 所指出的,最终的查询步骤可能比我最初声称的更糟糕:即使对于大小为 O(|V|) 的输出,也高达 O(|V|^2) ,比没有任何预处理的普通DFS好不了多少。].
在最坏的情况下,需要 O(|V|^2) 空间来显式存储所有这些信息——即,存储每个顶点的可到达顶点的完整列表(想象一个图,其中每个顶点对每个其他顶点都有一条边)。但是可以用只需要 O(|V|) 空间的方式来表示它,并且这种表示可以在 O(|V|+|E|) 时间内构建, 并且对它的查询将只需要与答案大小(可达顶点数)成比例的时间。
基本思想是:一个strongly connected component(SCC)中的每个顶点都可以到达同一个SCC中的每个其他顶点(这是SCC的定义),并且可以到达它所能到达的SCC中的所有顶点,并且没有其他顶点。
所以,给定 G 中的一个顶点 u,查找它的 SCC,SCC(u)。称之为我。从顶点 i 开始通过 G' 执行 DFS:对于在此 DFS 期间遇到的每个 (G') j 顶点,输出 Verts(j) 中的每个 (G) 顶点。
【讨论】:
O(n^2)),但最多有O(n) 可达顶点。所以从第三层的所有顶点运行 DFS 会产生O(n^3) 时间,这并不比一个幼稚的解决方案好。
我真的怀疑没有已知的更好的通用图算法。我在主题 [1] [2] 上找到的所有论文都描述了在 O(|V| * |E|) 时间内运行的算法。这并不比你在最坏情况下的幼稚尝试更好。
即使是维基百科页面 [3] 也说最快的算法将问题简化为矩阵乘法,最快的算法只比你的基线稍微好一点。
[1]http://ion.uwinnipeg.ca/~ychen2/conferencePapers/tranRelationCopy.pdf
[2]http://www.vldb.org/conf/1988/P382.PDF
[3]http://en.wikipedia.org/wiki/Transitive_closure#Algorithms
【讨论】: