問題描述
給定乙個n個頂點,m條邊的有向圖(其中某些邊權可能為負,但保證沒有負環)。請你計算從1號點到其他點的最短路(頂點從1到n編號)。
輸入格式
第一行兩個整數n, m。
接下來的m行,每行有三個整數u, v, l,表示u到v有一條長度為l的邊。
輸出格式
共n-1行,第i行表示1號點到i+1號點的最短路。
樣例輸入
3 3
1 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,保證從任意頂點都能到達其他所有頂點。
單源點最短路徑
bellman-ford演算法
知識點:
1.鬆弛操作
d[v]=min(d[v],d[u]+w[u,v])
不斷降低原點到v點的最優值上界
2.鬆弛操作的性質
假設u到v的最短路是(u,x1,x2,......v),對(u,x1)(x1,x2)...(xn,v)依次(不必連續)進行鬆弛操作,最後可以得到d[v]
基本思路:
對於最壞情況,最短路有n-1個結點,所以要進行n-1次鬆弛
每次鬆弛顧及所有情況,所以每條邊要鬆弛一下
時間複雜度o(e*v),對於這道題超時了。
**如下:
#include#include#define inf 99999999
#define min(a,b) au=st;
poi->v=end;
poi->l=len;
poi->p=(struct edge*)malloc(sizeof(struct edge));
poi=poi->p;
}for(i=1;i<=n;i++)
d[i]=inf;
d[1]=0;
for(i=1;iu]v]=min(d[poi->v],d[poi->u]+poi->l);
poi=poi->p;
}for(i=2;i<=n;i++)
printf("%d\n",d[i]);
}
dijkstra演算法
基本思路:每次找距離小的點,更新以它為起點的邊的終點的距離值
主要操作:
1.儲存圖
鍊錶用head[結點]儲存以某結點為起點的一條邊的編號,再用next[邊]儲存與某邊共起點的另一條邊,也能用指標
vector
乙個儲存邊結構,乙個儲存某個結點對應的邊序號
2.更新d[結點]原點到結點距離
有兩種,乙個是普通的外層結點數次迴圈,內層遍歷d找最小值,時間複雜度o(n^2)
還有一種需要使用優先佇列,先用結構重新定義優先順序,然後先放原點進去,遍歷以原點為起點的邊,鬆弛操作,其實就是把剩下
d存在的點放到佇列裡,原點出列,然後找d最小的點,。。。。。。。。
這裡有兩個問題
每次出列的是不是未標記的最小d的點?
每次更新後,d存在的點都放進了佇列,剩下的都是無窮大。
會不會有重複結點出現?
如果以u為起點的邊e,終點為v,然後更新後,又有乙個v點放入,會出現重複,加乙個done陣列即可。
時間複雜度o(邊數*log(結點數)),
ac**
#include
#include #include#include #include#include#includeusing namespace std;
#define min(a,b) ((aedge;
vectorg[20010];
void build()
};int done[20010]=;
void dijkstra(int s));
while(!q.empty()));
}}}}
int main()
藍橋杯 演算法訓練 最短路
問題描述 給定乙個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號點的最短路...