SPFA
SPFA 与 Dijkstra 一样,都是求最短路的算法,但 SPFA 可以求边权为负数的最短路。
SPFA 是基于 Bellman-Ford 算法的优化版本,Bellman-Ford 算法的核心是松弛操作,也就是更新最短路。
我们观察每一个没有负环的图,就会发现,每个点的最短路需要走的边数都不超过
每次松弛,我们遍历每一条边,如果从这条边的起点的最短路加边权小于终点的最短路,那我们就应该更新终点的最短路,和 Dijsktra 的松弛操作大致相同。
代码:
int u[M], v[M], w[M], dis[N];
void spfa(int n, int m, int s) {
memset(dis, INT_INF, sizeof dis);
dis[s] = 0;
for (int i = 1; i < n; i++) {
for (int j = 1; j <= m; j++) {
dis[v[j]] = min(dis[v[j]], dis[u[j]] + w[j]);
}
}
}
但这样做的时间复杂度到达了
这样做的时间复杂度会根据图的形状来改变,但在随机图的情况下效率较高。
代码:
struct node {
int p, w;
};
int dis[N];
bool vis[N];
vector<node> edge[N];
void spfa(int s) {
queue<int> q;
memset(dis, INT_INF, sizeof dis);
q.push(s);
dis[s] = 0;
vis[s] = true;
while (!q.empty()) {
int u = q.front(); q.pop();
vis[u] = false;
for (node i : edge[u]) {
if (dis[i.p] > dis[u] + i.w) {
dis[i.p] = dis[u] + i.w;
if (!vis[i.p]) {
q.push(i.p);
vis[i.p] = true;
}
}
}
}
}