1. 程式人生 > >Bellman-Ford 求含負權最短路

Bellman-Ford 求含負權最短路

操作 printf mat 時間復雜度 逆序輸出 sorry pri 復雜度 https

該算法詳解請看 https://www.cnblogs.com/tanky_woo/archive/2011/01/17/1937728.html

單源最短路 當圖中存在負權邊時 迪傑斯特拉就不能用了 該算法解決了此問題 時間復雜度O(nm)

註意 圖中含有負圈時不成立。當判定存在負圈時,這只說明s可以到達一個負圈,並不代表s到每個點的最短路都不存在。

另外,如果圖中有其他負圈但是s無法達到這個負圈,該算法也無法找到,解決方法加一個節點(還不會。。。)

該算法可以用 隊列 優化 名為spfa

下面給出 有向圖 的代碼

 1 #include <stdio.h>
 2
#include <math.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <iostream> 6 #include <sstream> 7 #include <algorithm> 8 #include <string> 9 #include <queue> 10 #include <ctime> 11 #include <vector> 12 using namespace std; 13
const int maxn= 1e3+5; 14 const int maxm= 1e3+5; 15 const int inf = 0x3f3f3f3f; 16 typedef long long ll; 17 int n,m,s; //n m s 分別表示 點數-標號從1開始 邊數-標號從0開始 起點 18 struct edge 19 { 20 int u,v,w; //u為邊的起點 v為邊的終點 w為邊的權值 21 }edges[maxm]; 22 int d[maxn]; //d[i]表示 i 點到源點 s 的最短距離 23 int p[maxn]; //p[i]記錄最短路到達 i 之前的節點
24 int Bellman_Ford(int x) 25 { 26 for(int i=1;i<=n;i++) 27 d[i]=inf; 28 d[x]=0; 29 for(int i=1;i<n;i++) // n-1次叠代 30 for(int j=0;j<m;j++) // 檢查每條邊 31 { 32 if(d[edges[j].u]+edges[j].w<d[edges[j].v]) // 松弛操作 33 { 34 d[edges[j].v]=d[edges[j].u]+edges[j].w; 35 p[edges[j].v]=edges[j].u; //記錄路徑 36 } 37 } 38 int flag=1; 39 for(int i=0;i<m;i++) //判斷是否有負環 40 if(d[edges[i].u]+edges[i].w<d[edges[i].v]) 41 { 42 flag=0; 43 break; 44 } 45 return flag; //返回最短路是否存在 46 } 47 void Print_Path(int x) 48 { 49 while(x!=p[x]) //逆序輸出 正序的話用棧處理一下就好了 50 { 51 printf("%d ",x); 52 x=p[x]; 53 } 54 printf("%d\n",x); 55 } 56 int main() 57 { 58 while(scanf("%d %d %d",&n,&m,&s)!=EOF) 59 { 60 for(int i=0;i<m;i++) 61 scanf("%d %d %d",&edges[i].u,&edges[i].v,&edges[i].w); 62 p[s]=s; 63 if(Bellman_Ford(s)==1) 64 for(int i=1;i<=n;i++) 65 { 66 printf("%d %d\n",i,d[i]); 67 Print_Path(i); 68 } 69 else 70 printf("sorry\n"); 71 return 0; 72 } 73 }

輸入

6 9 1
1 2 2
1 4 -1
1 3 1
3 4 2
4 2 1
3 6 3
4 6 3
6 5 1
2 5 -1

輸出
1 0
1
2 0
2 4 1
3 1
3 1
4 -1
4 1
5 -1
5 2 4 1
6 2
6 4 1

太菜了 wa~~

Bellman-Ford 求含負權最短路