spfa算法

用spfa求最短路(必须是不能有负权环的图,有负权可以):

给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。

请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出impossible。

数据保证不存在负权回路。

输入格式

第一行包含整数n和m。

接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。

输出格式

输出一个整数,表示1号点到n号点的最短距离。

如果路径不存在,则输出”impossible”。

数据范围

1n,m1051≤n,m≤105,
图中涉及边长绝对值均不超过10000。

输入样例:

3 3
1 2 5
2 3 -3
1 3 4

输出样例:

2


 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 //优化的贝尔曼福特算法,就是spfa算法,用更新过的点去更新和它相连接的点
 4 const int N = 1e5+10;
 5 vector<int> h(N, -1), e(N, 0), w(N,0), ne(N, 0);
 6 int idx;
 7 vector<int> dist(N, 0x3f3f3f3f);
 8 vector<bool> flag(N,false);//代表该节点当前是否在队列里
 9 int n, m;
10 
11 void add(int a, int b, int c){
12     w[idx] = c; e[idx] = b;       
13     ne[idx] = h[a];
14     h[a] = idx ++;
15 }
16 
17 int spfa(){
18     queue<int> q;//队列中存储的是已经更新过用来更新其他节点的点
19     q.push(1);
20     dist[1] = 0;
21     flag[1] = true;
22     while(!q.empty()){
23         int t = q.front(); q.pop();
24         flag[t] = false;//不在队列里
25         for(int i = h[t];i != -1;i = ne[i]){
26             int j = e[i];
27             //更新成功
28             if(dist[j] > dist[t] + w[i]){
29                 dist[j] = dist[t] + w[i];
30                 if(!flag[j]) {//如果j不在队列里
31                     q.push(j);
32                     flag[j] = true;//放进队列里
33                 }
34             }
35         }
36     }
37     return dist[n] == 0x3f3f3f3f ? -1 : dist[n];
38 }
39 
40 int main(){
41     cin >> n >> m;
42     while(m--){
43         int x, y, z;
44         cin >> x >> y >> z;
45         add(x, y, z);
46     }
47     int t = spfa();
48     if(t == -1) cout << "impossible" << endl;
49     else cout << t << endl;
50 }
View Code

end

原文地址:https://www.cnblogs.com/sxq-study/p/12236587.html