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 附上 注釋...