原题链接:
题解:
相比于Bellman_ford算法的O(mn)复杂度,SPFA算法在最好情况下的时间复杂度为O(m),最坏情况下的时间复杂度则为O(mn)
代码:
虽然用STL实现邻接表更简单,但是还是链星的时间开销更小
用STL实现邻接表:
#pragma GCC optimize(2, 3, "Ofast", "inline")
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int dis[N], state[N];
vector<pair<int,int>> v[N];//存储的是终点编号-距离
int n, m;
int spfa() {
memset(dis, 0x3f, sizeof(dis));
dis[1] = 0;
queue<int> q;
q.push(1);
state[1] = 1;
while (q.size()) {
int F = q.front();
q.pop();
state[F] = 0;
for (int i = 0;i < v[F].size();i++) {
int y = v[F][i].first, z = v[F][i].second;
if (dis[y] > dis[F] + z) {
dis[y] = dis[F] + z;
if (!state[y]) {
q.push(y);
state[y] = 1;
}
}
}
}
if (dis[n] == 0x3f3f3f3f) return -1;
//因为较大的值也会被更新为较小的值,所以在一定数据范围内,可以假定这个数如果大于0x3f3f3f3f / 2就比表示不存在满足条件的路径
return dis[n];
}
int main() {
cin >> n >> m;
for (int i = 0;i < m;i++) {
int x, y, z;cin >> x >> y >> z;
v[x].push_back({ y,z });
}
int t = spfa();
if (t == -1 && dis[n] != -1) cout << "impossible";//还有一种可能就是最小距离就是-1,因此需要特判一下
else cout << t;
}
用手搓链表(链星)实现邻接表:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
#define fi first
#define se second
typedef pair<int, int> PII;//到源点的距离,下标号
int h[N], e[N], w[N], ne[N], idx = 0;
int dist[N];//各点到源点的距离
bool st[N];
int n, m;
void add(int a, int b, int c) {
e[idx] = b;w[idx] = c;ne[idx] = h[a];h[a] = idx++;
}
int spfa() {
queue<PII> q;
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
q.push({ 0,1 });
st[1] = true;
while (q.size()) {
PII p = q.front();
q.pop();
int t = p.se;
st[t] = false;//从队列中取出来之后该节点st被标记为false,代表之后该节点如果发生更新可再次入队
for (int i = h[t];i != -1;i = ne[i]) {
int j = e[i];
if (dist[j] > dist[t] + w[i]) {
dist[j] = dist[t] + w[i];
if (!st[j]) {//当前已经加入队列的结点,无需再次加入队列,即便发生了更新也只用更新数值即可,重复添加降低效率
st[j] = true;
q.push({ dist[j],j });
}
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
else return dist[n];
}
int main() {
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m--) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
int res = spfa();
if (res == -1&& dist[n] != -1) puts("impossible");
else printf("%d", res);
return 0;
}