SPFA

发布时间 2023-08-12 22:48:23作者: ChElsYqwq

给定一张 \(n\) 个点、\(m\) 条边的有向图,求 \(1\) 号点到每个点的最短路径长度。


我们用 \(dis_{i}\) 表示从点 \(1\) 到点 \(i\) 的最短距离。

  • 初始化 \(dis_{1}\)\(0\),其余为无穷大,搞一个队列并将起点入队

  • 取队头 \(x\),遍历它的出边 \(x\)\(y_i\) ,若 \(dis_{y_i}>dis_x+w_{x,y_i}\), 则 \(dis_{y_i}\gets dis_x+w_{x,y_i}\) 并将 \(y_i\) 入队

  • 重复第二步,直到队列为空

如果起点不是 \(1\) ,就按需求调整起始点。

复杂度为 \(O(kn)\),注意可能退化到 \(O(nm)\),可以搞负权

spfa粗浅的证明

迭代思想,最后这个图肯定满足三角不等式

int n, m, u, v, w;
vector<int>to[MN], eg[MN];
int dis[MN]; bool vis[MN];
queue<int>q;
void spfa() {
	for(int i=1; i<=n; ++i) dis[i]=INF, vis[i]=0;
	dis[1]=0; q.push(1);
	while(q.size()) {
		int val=q.front(); q.pop();
		for(int i=0; i<to[val].size(); ++i) {
			int j=to[val][i], k=eg[val][i];
			if(dis[j]>dis[val]+k) {
				dis[j]=dis[val+k];
				q.push(j);
			}
		}
	}
}