给定一个循环图,我正在寻找一个将此图分解为非循环子图的算法。这些子图中的每一个都有一个根顶点,这个顶点是计算最短路径的源。例如,下面给出的循环图,其中,所述周期是3,4之间,和5:将循环图分解为最短路径子图的最小数目
+-------------------------+
| |
| |
+----------+----------+ |
v | v |
+---+ +---+ +---+ +---+ +---+ |
| 1 | --> | 3 | <--> | 4 | <--> | 5 | --> | 6 | |
+---+ +---+ +---+ +---+ +---+ |
^ |
| |
| |
+---+ |
| 2 | |
+---+ |
+---+ |
| 7 | <---------------------+
+---+
相对于最短路径的子图1是:
+---+ +---+ +---+ +---+
| 1 | --> | 3 | --> | 4 | --> | 7 |
+---+ +---+ +---+ +---+
|
|
v
+---+ +---+
| 5 | --> | 6 |
+---+ +---+
最短路径的子图相对于2将是:
+---+
| 7 |
+---+
^
|
|
+---+ +---+ +---+ +---+
| 2 | --> | 4 | --> | 5 | --> | 6 |
+---+ +---+ +---+ +---+
|
|
v
+---+
| 3 |
+---+
相对于最短路径sugraph至5将是:
+---+ +---+ +---+ +---+
| 6 | <-- | 5 | --> | 4 | --> | 7 |
+---+ +---+ +---+ +---+
|
|
v
+---+
| 3 |
+---+
注意,关于3的最短路径子图是1的子集,4是2的子集。 6和7是叶子。
我目前的(天真的)解决方案将是为每个节点执行一个BFS,标记节点访问以防止周期。然后检查子图是否是彼此的子集以创建最小数量的不同子图。任何更好,更正式的解决方案的想法?
编辑在我的情况图是不加权的,但有后人的一般解决方案是很好的。
(与http://bloodgate.com/graph-demo由图)
@食谱 - 我发现一篇论文,有人想出了一个非常快的APSP算法,并将其添加到我的答案中。另外,我对你的算法有点怀疑,因为我不认为你的“包含”的定义必然是正确的。仅仅因为你可以达到与v相同的一组顶点,并不意味着v中的BFS树将被包含在U的BFS树中。或者我错了吗? – templatetypedef
@templatetypedef我说:“显然你只包含v_only if_ ...”,不是当且仅当。换句话说,可能有从u到v的路径,但是u不包含v。在第二阶段中将误报消除。另外,您链接的论文是关于节省时间的;如果OP仍然愿意运行所有的BFS,那么似乎时间不是问题,但只有OP可以肯定地告诉我们。 – comestibles
@食品 - 啊,我的错误,我误解了。回顾一下,看起来在最糟糕的情况下,你需要运行O(n)不同的BFS迭代,这会得到O(n(n + m))= O(n^2 + nm)的运行时间, ,其中m = o(n log n)的图比迭代的Dijkstra更好,对于m = o(n^2)的图更好于Floyd-Warshall。非常好! – templatetypedef