我在一次采访中被问到了这个问题,但我无法想出任何像样的解决方案。所以,我告诉他们寻找所有循环的幼稚方法,然后选择最短的循环。在有向图中找到正长度的最短长度的循环
我很想知道什么是这个问题的有效解决方案。
我在一次采访中被问到了这个问题,但我无法想出任何像样的解决方案。所以,我告诉他们寻找所有循环的幼稚方法,然后选择最短的循环。在有向图中找到正长度的最短长度的循环
我很想知道什么是这个问题的有效解决方案。
您可以轻松地修改Floyd-Warshall algorithm见Algorithms in C++ Part5 - Robert Sedgwick
。 (如果你根本不熟悉图论,我建议检查一下,例如获得Introduction to Algorithms的副本)。
传统上,您每个i
开始path[i][i] = 0
。但是你可以从path[i][i] = INFINITY
开始。它不会影响算法本身,因为无论如何这些零都不用于计算(因为路径path[i][j]
将永远不会改变为k == i
或k == j
)。
最后,path[i][i]
是最短周期长度为i
的长度。因此,您需要为所有i
找到min(path[i][i])
。如果你想自行循环(不仅是它的长度),你可以像使用正常路径一样完成它:通过在执行算法期间记住k
。
另外,您还可以使用Dijkstra's algorithm来查找经过任何给定节点的最短周期。如果你为每个节点运行这个修改后的Dijkstra,你将得到与Floyd-Warshall相同的结果。而且由于每个Dijkstra都是O(n^2)
,你会得到相同的整体复杂度。
Tree Edge
,Back Edge
,Down Edge
和Parent Edge
Back Edge
并有另一个柜台为了获得长度。更多细节
不错的尝试,但这最多是指数复杂。我怀疑,罗伯特塞奇威克在他的书中解决了一些更普遍和更复杂的问题,因为这个更容易。 – 2010-10-12 07:52:27
你将不得不做的是为每个始终为1的节点分配另一个权重。现在使用这些权重从一个节点到同一节点运行任何最短路径算法。但在考虑中间路径时,您将不得不忽略实际权重为负的路径。
伪代码是对Dijkstra算法的简单修改。
for all u in V:
for all v in V:
path[u][v] = infinity
for all s in V:
path[s][s] = 0
H = makequeue (V) .. using pathvalues in path[s] array as keys
while H is not empty:
u = deletemin(H)
for all edges (u,v) in E:
if path[s][v] > path[s][u] + l(u, v) or path[s][s] == 0:
path[s][v] = path[s][u] + l(u,v)
decreaseKey(H, v)
lengthMinCycle = INT_MAX
for all v in V:
if path[v][v] < lengthMinCycle & path[v][v] != 0 :
lengthMinCycle = path[v][v]
if lengthMinCycle == INT_MAX:
print(“The graph is acyclic.”)
else:
print(“Length of minimum cycle is ”, lengthMinCycle)
时间复杂度:O(| V |^3)
我们也可以使用分支定界算法旅行商问题,你的问题与TSP相匹配。 http://lcm.csa.iisc.ernet.in/dsa/node187.html
这不符合要求。在这些算法中,最短意味着最小权重而不是最小长度。例如如果有两个周期,例如1,2,3和100,500;那么将选择循环1,但是由于循环2具有最短的长度,所以需要循环2。纠正我,如果我错了。 – 2010-10-12 09:59:51
@Manoj第二个问题是第一个子集。只需将权重1分配给每个边,并且您将收到边数最少的路径。真正的问题(尽管很小)是因为Dijkstra和Floyd-Warshal都找不到从节点回到自身的最短路径。你必须稍微调整一下。 – 2010-10-12 10:52:56
谢谢..我使用Dijkstra的修改版本,它的工作 – 2010-10-12 13:14:20