算法訓練 最短路
時間限制:1.0s 內存限制:256.0MB
問題描述
給定一個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,保證從任意頂點都能到達其他所有頂點。
SPFA算法:解決有向負權邊
- 算法大致流程是用一個隊列來進行維護。 初始時將源加入隊列。 每次從隊列中取出一個元素,
- 並對所有與他相鄰的點進行鬆弛,若某個相鄰的點鬆弛成功,則將其入隊。 直到隊列爲空時算法結束。
- 它可以在O(kE)的時間複雜度內求出源點到其他所有點的最短路徑,可以處理負邊。
queue: q.front();
q.pop();
q.push();
#include<stdio.h>
#include<iostream>
using namespace std;
#define N 200001
#include<vector>
#include<queue>
typedef struct{
int v;
int w;
}node;
vector<node> g[N]; //一行最多有N這麼多的鄰接點
queue<node> q;
int inqueue[N], dist[N];
void spfa(){
node e;
int i, j, len;
int start = 1;
e.v = 1;
e.w = 0;
q.push(e);
for(i = 0; i < N; i++){
dist[i] = N;
}
dist[1] = 0;
inqueue[1] = 1;
while(!q.empty()){
e = q.front();
q.pop();
int now = e.v;
len = g[now].size();
for(i = 0; i < len; i++){
node next = g[now][i];
if(next.v != 1 && (g[now][i].w + dist[now] < dist[next.v])){//不是源, 而且加上這條邊, 小於記錄的
dist[next.v] = g[now][i].w + dist[now];
if(inqueue[next.v] == 0){
q.push(next);
inqueue[next.v] = 1;
}
}
}
inqueue[now] = 0;//出隊,標記爲不在隊中中
}
}
int main(){
// freopen("in.txt", "r", stdin);
node e;
int n, m;
int u, v, l;
scanf("%d%d", &n, &m);
while(m--){
scanf("%d%d%d", &u, &v, &l);
e.v = v;
e.w = l;
g[u].push_back(e);//存儲有向圖
}
spfa();
for(int i = 2; i <= n; i++){//明確用什麼參數記錄的點的數目
printf("%d\n", dist[i]);
}
return 0;
}