原文:
問題描述
給定乙個n個頂點,m條邊的有向圖(其中某些邊權可能為負,但保證沒有負環)。請你計算從1號點到其他點的最短路(頂點從1到n編號)。
輸入格式
第一行兩個整數n, m。
接下來的m行,每行有三個整數u, v, l,表示u到v有一條長度為l的邊。
輸出格式
共n-1行,第i行表示1號點到i+1號點的最短路。
樣例輸入
3 31 2 -1
2 3 -1
3 1 2
樣例輸出
-1-2
資料規模與約定
對於10%的資料,n = 2,m = 2。
對於30%的資料,n <= 5,m <= 10。
對於100%的資料,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保證從任意頂點都能到達其他所有頂點。
我在網上搜尋了最短路演算法,發現基本有4種。
1.floyd 演算法 2.dijkstra演算法 3.bellman演算法 4.spfa演算法
floyd演算法時間複雜度高,dijkstra演算法不能計算帶負邊權的圖,故均不考慮。
spfa演算法是bellman的一種優化,所以決定從簡單的先開始。
bellman實現的**如下:
#include #includeusing namespace std;
int dis[20005],u[200005],v[200005],w[200005];//dis[i]代表第一點到第i點距離,u[i],v[i],w[i]分別代表第i條邊的起始點,終點和長度。
int main()
memset(dis,10001,sizeof(dis));
dis[1]=0;
for(int k=1;kdis[u[i]]+w[i])
//如果第一點到v[i]點的距離大於第一點到u[i]再加上u[i]到v[i]的距離
dis[v[i]]=dis[u[i]]+w[i];//說明dis[v[i]]的值可以更小,所以更新dis[v[i]]的值,專業的說法就是進行了一次鬆弛操作}}
for(int i=2;i<=n;i++)
cout《這段**很簡單,最關鍵的地方在兩層for迴圈的那部分。演算法的時間複雜度顯然是o(mn),最後提交超時。
**的缺點在於不是所有的點都要鬆弛n-1次,並且絕大部分的點鬆弛的次數都遠小於n-1,這就造成了大量的不必要的運算。
spfa(shortest path faster algorithm)演算法是求單源最短路徑的一種演算法,它是bellman-ford的佇列優化,它是一種十分高效的最短路演算法。
spfa的複雜度大約是o(ke),k是每個點的平均進隊次數(一般的,k是乙個常數,在稀疏圖中小於2)。
但是,spfa演算法穩定性較差,在稠密圖中spfa演算法時間複雜度會退化。
實現方法:建立乙個佇列,初始時佇列裡只有起始點,在建立乙個**記錄起始點到所有點的最短路徑(該**的初始值要賦為極大值,該點到他本身的路徑賦為0)。然後執行鬆弛操作,用佇列裡有的點去重新整理起始點到所有點的最短路,如果重新整理成功且被重新整理點不在佇列中則把該點加入到佇列最後。重複執行直到隊列為空。
此外,spfa演算法還可以判斷圖中是否有負權環,即乙個點入隊次數超過n。
#include #include#includeusing namespace std;
struct edge
e[200100];//e[i].to,e[i].val,e[i].next分別表示第i條邊的終點,權值,和另(上)一條於此邊相同起點的邊的編號
int m,n,head[21000],dis[21000];//head[i]表示當前以i為起點的邊的編號,dis[i]表示1號點到i號點的距離
void add(int from,int to,int val,int len)//新增邊,引數分別代表此邊的起點,終點,權值,還有此邊的編號
void spfa()
//將權值初始化為最大值
memset(visit,0,sizeof(visit));//初始沒有點在佇列中
dis[1]=0;
q.push(1);
visit[1]=1;//現在把第乙個點扔進佇列
while(!q.empty())//如果佇列不空則重複執行以下操作
//如果成功鬆弛了s點,把s點扔進佇列}}
}}
int main ()
spfa();
for(int i=2;i<=n;i++)
}
藍橋杯 演算法訓練 最短路
問題描述 給定乙個n個頂點,m條邊的有向圖 其中某些邊權可能為負,但保證沒有負環 請你計算從1號點到其他點的最短路 頂點從1到n編號 輸入格式 第一行兩個整數n,m。接下來的m行,每行有三個整數u,v,l,表示u到v有一條長度為l的邊。輸出格式 共n 1行,第i行表示1號點到i 1號點的最短路。樣例...
演算法訓練 最短路 藍橋杯
問題描述 給定乙個n個頂點,m條邊的有向圖 其中某些邊權可能為負,但保證沒有負環 請你計算從1號點到其他點的最短路 頂點從1到n編號 輸入格式 第一行兩個整數n,m。接下來的m行,每行有三個整數u,v,l,表示u到v有一條長度為l的邊。輸出格式 共n 1行,第i行表示1號點到i 1號點的最短路。樣例...
藍橋杯 演算法訓練 最短路
問題描述 給定乙個n個頂點,m條邊的有向圖 其中某些邊權可能為負,但保證沒有負環 請你計算從1號點到其他點的最短路 頂點從1到n編號 輸入格式 第一行兩個整數n,m。接下來的m行,每行有三個整數u,v,l,表示u到v有一條長度為l的邊。輸出格式 共n 1行,第i行表示1號點到i 1號點的最短路。樣例...