SPFA板子 (背景:Luogu P3371 單源最短路徑)
阿新 • • 發佈:2018-04-30
數組 ons orange radius site 是否 -c class 所在
Luogu P3371 單源最短路徑
題目描述
如題,給出一個有向圖,請輸出從某一點出發到所有點的最短路徑長度。
輸入輸出格式
輸入格式:
第一行包含三個整數N、M、S,分別表示點的個數、有向邊的個數、出發點的編號。
接下來M行每行包含三個整數Fi、Gi、Wi,分別表示第i條有向邊的出發點、目標點和長度。
輸出格式:
一行,包含N個用空格分隔的整數,其中第i個整數表示從點S出發到點i的最短路徑長度(若S=i則最短路徑長度為0,若從點S無法到達點i,則最短路徑長度為2147483647)
輸入輸出樣例
輸入樣例#1:4 6 1 1 2 2 2 3 2 2 4 1 1 3 5 3 4 3 1 4 4
輸出樣例#1:
0 2 4 3
分析:
啊無負邊權的有向圖的單源最短路徑
代碼+註釋:
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <vector> 5 #define MAXN 10005 6 #define MAXM 500005 7 using namespace std; 8 9 const long long MAX = 2147483647; 10 11 int n, m, p_st; 12 int x, y, d;13 vector<int> l[MAXN], dis[MAXN]; //采用鄰接表的存儲方式 14 int ans_dis[MAXN]; //答案儲存數組 15 bool visited[MAXN]; //標記是否被訪問過 16 17 void read(int a, int b, int d) { //鄰接表的讀入 18 l[a].push_back(b); 19 dis[a].push_back(d); 20 } 21 22 void spfa() { //不就是按照BFS打一波… 23 24 queue<int> q; //新建隊列 25 visited[p_st] = true; //源點設為已經訪問過了 26 ans_dis[p_st] = 0; //到源點的最短路徑為0 27 q.push(p_st); //進隊開始BFS 28 29 while (!q.empty()) { //開始BFS 30 int now = q.front(); //now為目前所在的點 31 for (int i = 0; i < l[now].size(); i++) { //在它周圍可以去到的點裏繞一圈 32 int u = l[now][i], v = dis[now][i]; //u表示目前遍歷到的點 v為目前的點到u的距離 33 if (ans_dis[u] > ans_dis[now] + v) //若可更新距離 34 { 35 ans_dis[u] = ans_dis[now] + v; //更新 36 if (!visited[u]) { 37 visited[u] = true; //標記訪問過 38 q.push(u); //拉進隊列 39 } 40 } 41 } 42 43 visited[now] = false; // 不要忘記打這一句兄dei SFPA和BFS不同點 44 q.pop(); // 出隊 45 } 46 47 } 48 49 int main() { 50 51 scanf("%d%d%d", &n, &m, &p_st); //N為點的個數 M為有向邊的個數 P_ST為出發點的編號 52 for (int i = 1; i <= n; i++) 53 ans_dis[i] = MAX / 3; //當然是為了防止判斷的時候爆炸而設定的 54 for (int i = 1; i <= m; i++) { 55 scanf("%d%d%d", &x, &y, &d); 56 read(x, y, d); 57 } 58 59 spfa(); 60 61 for (int i = 1; i <= n; i++) 62 if (ans_dis[i] == MAX / 3) printf("%lld ", MAX); //到不了這個點 63 else printf("%d ", ans_dis[i]); //到得了就輸出 64 65 return 0; 66 }
(僅供個人復習使用)
SPFA板子 (背景:Luogu P3371 單源最短路徑)