SPFA板子 (背景:Luogu P3371 单源最短路径)
Luogu P3371 单源最短路径
题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
输入输出格式
输入格式:
第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。
接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。
输出格式:
一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)
输入输出样例
输出样例#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 }
(仅供个人复习使用)