spfa算法
该算法是对Bellman-Ford优化
时间复杂度:O(m)
SPFA只要不是负环就能用,一般用于求单源最短路问题
思路:
把1号点加入到队列(对列里边存的是所有距离变小了的节点编号)
循环,队列不为空:
1.取出队头元素
2.遍历t的所有出边
- 2.1更新t指向的每个点
- 2.2如果一个点更新成功,加入到队列
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1000010;
const int INF = 0x3f3f3f3f;
int n, m;
// 每个节点的距离和编号
typedef pair<int, int> PII;
// 稀疏图,邻接表存图
int h[N], e[N], ne[N], idx;
int w[N];// 每条边的权重
// 表示每个点当前,从1号点走到他自己的最短距离
int dist[N];
// 表示这个点在 不在队列里面
int st[N];
int spfa()
{
queue<int> q;
// 初始化距离数组
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
// 1号点入队
q.push(1);
st[1] = true;
while (q.size())
{
int t = q.front();
q.pop();
// 弹出去之后,这个点就不在队列里面了
st[t] = false;
// 更新t指向的每个点
for (int i = h[t]; i != -1; i = ne[i])
{
// e[i]中在存的是i这个下标对应的点的编号
int j = e[i];
// 如果1号点到当前点j的距离大于从1到t再到j的距离
if (dist[j] > dist[t] + w[i])
{
// 更新从1号点到j点的距离
dist[j] = dist[t] + w[i];
// 如果这个点不在队列里面
if (!st[j])
{
q.push(j);
st[j] = true;
}
}
}
}
return dist[n];
}
// 添加一条边 a指向b
// c是边的权重
void add(int a, int b, int c)
{
w[idx] = c;
e[idx] = b;
ne[idx] = h[a];
h[a] = idx;
idx++;
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
while (m--)
{
int a, b, c;
cin >> a >> b >> c;
// 邻接表存图不需要对重边进行处理
add(a, b, c);
}
int t = spfa();
if (t == INF)
{
cout << "impossible";
}
else
cout << t;
cout << endl;
return 0;
}