2010-10-12 74 views

回答

19

您可以輕鬆地修改Floyd-Warshall algorithmAlgorithms in C++ Part5 - Robert Sedgwick。 (如果你根本不熟悉圖論,我建議檢查一下,例如獲得Introduction to Algorithms的副本)。

傳統上,您每個i開始path[i][i] = 0。但是你可以從path[i][i] = INFINITY開始。它不會影響算法本身,因爲無論如何這些零都不用於計算(因爲路徑path[i][j]將永遠不會改變爲k == ik == j)。

最後,path[i][i]是最短週期長度爲i的長度。因此,您需要爲所有i找到min(path[i][i])。如果你想自行循環(不僅是它的長度),你可以像使用正常路徑一樣完成它:通過在執行算法期間記住k

另外,您還可以使用Dijkstra's algorithm來查找經過任何給定節點的最短週期。如果你爲每個節點運行這個修改後的Dijkstra,你將得到與Floyd-Warshall相同的結果。而且由於每個Dijkstra都是O(n^2),你會得到相同的整體複雜度。

+0

這不符合要求。在這些算法中,最短意味着最小權重而不是最小長度。例如如果有兩個週期,例如1,2,3和100,500;那麼將選擇循環1,但是由於循環2具有最短的長度,所以需要循環2。糾正我,如果我錯了。 – 2010-10-12 09:59:51

+0

@Manoj第二個問題是第一個子集。只需將權重1分配給每個邊,並且您將收到邊數最少的路徑。真正的問題(儘管很小)是因爲Dijkstra和Floyd-Warshal都找不到從節點回到自身的最短路徑。你必須稍微調整一下。 – 2010-10-12 10:52:56

+0

謝謝..我使用Dijkstra的修改版本,它的工作 – 2010-10-12 13:14:20

0
  • 執行DFS
  • DFS期間保持邊緣類型的軌道
  • 型邊緣的位置是Tree EdgeBack EdgeDown EdgeParent Edge
  • 跟蹤,當你得到一個Back Edge並有另一個櫃檯爲了獲得長度。

更多細節

+0

不錯的嘗試,但這最多是指數複雜。我懷疑,羅伯特塞奇威克在他的書中解決了一些更普遍和更復雜的問題,因爲這個更容易。 – 2010-10-12 07:52:27

0

你將不得不做的是爲每個始終爲1的節點分配另一個權重。現在使用這些權重從一個節點到同一節點運行任何最短路徑算法。但在考慮中間路徑時,您將不得不忽略實際權重爲負的路徑。

5

僞代碼是對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)