spfa 的算法实现之一
问题描述:
给定一个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,保证从任意顶点都能到达其他所有顶点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
#include <stdio.h> #include <queue> #include <string.h> #define Infinite 210000000 #define ListEndFlag -1 int number_vertex; int number_edge; int dist[20010]; int head[20010]; struct { int to, w, next; }edge[200010]; void SPFA() { // 用于标识顶点是否在队列中 bool isAlreadyInQueue[20010]; // 初始化数据 for ( int i = 2; i <= number_vertex; i++) { dist[i] = Infinite; isAlreadyInQueue[i] = false ; } dist[1] = 0; isAlreadyInQueue[1] = true ; std::queue< int > q; q.push(1); while (q.empty() == false ) { const int x = q.front(); for ( int i = head[x]; i != ListEndFlag; i = edge[i].next) { const int y = edge[i].to; const int w = edge[i].w; if (dist[x] + w < dist[y]) { dist[y] = dist[x] + w; if (isAlreadyInQueue[y] == false ) { q.push(y); isAlreadyInQueue[y] = true ; } } } q.pop(); isAlreadyInQueue[x] = false ; } } int main() { // 1. 读取顶点数,边数 scanf ( "%d%d" , &number_vertex, &number_edge); // 2. 设置 flag memset (head, ListEndFlag, sizeof (head)); // 3. 读取边 for ( int i = 1; i <= number_edge; i++) { int x, y, w; scanf ( "%d%d%d" , &x, &y, &w); edge[i].to = y; edge[i].w = w; edge[i].next = head[x]; head[x] = i; } // 4. 执行 SPFA SPFA(); // 5. 输出结果 for ( int i = 2; i <= number_vertex; i++) { printf ( "%d\n" , dist[i]); } return 0; } |