Bell Ford 演算法的改進 SPFA演算法

2021-07-26 14:40:53 字數 2103 閱讀 1716

bellman—ford演算法的時間複雜度比較高,原因在於bellman—ford演算法要遞推n次,每次遞推,掃瞄所有的邊,在遞推n次的過程中很多判斷是多餘的,spfa演算法是bellman—ford演算法的一種佇列實現,減少了不必要的冗餘判斷。

大致流程:用乙個佇列來進行維護。初始時將源點加入佇列。每次從佇列中取出乙個頂點,並與所有與它相鄰的頂點進行鬆弛,若某個相鄰的頂點鬆弛成功,則將其入隊。重複這樣的過程直到隊列為空時演算法結束。

實現過程:(1)取出佇列頭頂點v,掃瞄從頂點v發出的每條邊,設每條邊的終點為u,邊的權值為w,如果dist[v]+w(2)重複執行上述過程直至隊列為空。

上面看起來好抽象,舉個栗子吧:

假設頂點3在佇列中,取出頂點3,這時有個問題?從源點經過頂點3 到3的鄰接點2和5的距離是否比之前更短呢?可能的情況:

dist[3]+w(3,2), dist[3]+w(3,5)分別和dist[2]與dist[5]進行比較,如果更短的話,則更新dist[2],dist[5]。如果被更新且不在佇列中,則要入隊。

例題:求頂點0到其他各頂點的最短路徑長度,並輸出相應的最短路徑

測試資料:

輸入:7

0 1 6

0 2 5

0 3 5

1 4 -1

2 1 -2

2 4 1

3 2 -2

3 5 -1

4 6 3

5 6 3

-1 -1 -1

輸出:1          0-3-2-1

3          0-3-2

5          0-3

0          0-3-2-1-4

4          0-3-5

3          0-3-2-1-4-6

#include#include#include#includeusing namespace std;

#define inf 999999

#define maxn 110

struct arcnode

;queueq;

int n;

arcnode *list[maxn];///定義了一大堆只能存放結點位址的指標,用來當做邊鍊錶的表頭指標

int inq[maxn];

int dist[maxn],path[maxn];

void spfa(int src)///求源點src到其他各點的最路徑長度

///如果頂點v不在佇列中,入隊

}temp=temp->next;}}

}int main()

}spfa(0);///求頂點0到其他各點的最短路徑

for(j=0;jnext;///儲存下乙個

delete temp;///刪除這乙個

temp=list[u];///定位下乙個}}

int shortest[maxn];

for(i=1;i0;j--)

printf("%d->",shortest[j]);

printf("%d\n",shortest[0]);

}return 0;}/*

/*測試資料:

輸入:7

0 1 6

0 2 5

0 3 5

1 4 -1

2 1 -2

2 4 1

3 2 -2

3 5 -1

4 6 3

5 6 3

-1 -1 -1

輸出:1 0->3->2->1

LCS 演算法的改進

通常兩個字串的最大公共子串的問題是通過下面的演算法來完成的 把字串1 長度m 橫排,串2 長度n 豎排,得到乙個m n的矩陣c,矩陣的每個元素的值如下,如果m i n j 則c j i 1,否則,c j i 0。然後找出矩陣中連續是1的對角線最長的乙個,則對角線的長度就是公共子串的長度.一看這個方法...

冒泡演算法的改進

氣泡排序演算法的思想 首先將第乙個記錄的關鍵字和第二個關鍵字進行比較,若為逆序則將兩個記錄進行交換。然後比較第二個記錄和第三個記錄的關鍵字,直至第n 1個記錄和第n個記錄進行比較為止,一趟過後最大的元素會沉入最底部。然後進行第二趟排序,對前 n 1 個記錄進行同樣1 2的操作,結果就是關鍵字次大的記...

dinic演算法的改進

儲存鄰接表是使用的是head陣列,現在另設乙個head2陣列,儲存的是每個節點x從head2 x 開始的邊才會有增廣路,這樣減少了無用邊的迴圈。並且head2陣列只在全域性初始化一次,即如果沒有增廣,該值只會逐漸減小直到0。在hdu3572中使用該優化可使時間從998ms優化值156ms 附上 注釋...