最短路算法学习笔记

Dijkstra

Dijkstra 是基于贪心的一种算法,适用于非负权的图,求解单源最短路。
算法是这样的:
找出全局距离最小的点 u,并用这个点去更新连接它的 v 点的距离。
时间复杂度 O(n^2),使用堆优化可以优化到 O(m log m)

code
struct node{
	int x;
	LL y;
	bool operator < (const node& no) const{
		return no.y < y;
	}
};
priority_queue <node> q;
void dij(int u){
	memset(dis,0x7f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[u] = 0;
	q.push(node{u,0});
	while(!q.empty()){
		node tmp = q.top();
		q.pop();
		int x = tmp.x;
		if(vis[x]) continue;
		vis[x] = 1;
		for(int i = head[x];i;i = e[i].next){
			int y = e[i].to,z = e[i].val;
			if(dis[y] > dis[x] + z){
				dis[y] = dis[x] + z;
				q.push(node{y,dis[y]}); 
			}	
		}
	}
}
Bellman_Ford

是一种可以处理负权的单源最短路算法。
算法是这样的:
枚举每条边,并更新这条边上点,称为一次松弛。
重复上诉操作直到没有点被更新。
如果经过了 n 轮松弛后还存在有点被更新,则原图存在负环。
时间复杂度 O(nm).

SPFA

SPFA 是 Bellman_Ford 的队列优化。
松弛节点 x 时找到接下来有可能松弛的点,
即与 x 相邻且最短路被更新的点压入队列。
判断负环只需要是否存在点判断进入队列是否超过 n−1 次。
若有,则有负环。

在一般图上效率很高,但是会被构造数据卡成 O(nm).

code
 void spfa() {
	memset(dis,0x7f,sizeof(dis));
	q.push(s),dis[s] = 0;
	while(!q.empty()){
		int x = q.front();
		q.pop();
		vis[x]=0;
		for(int i = head[x];i;i = e[i].next) {
			int y = e[i].to,z = e[i].val;
			if(dis[y] > dis[x] + z) {
				dis[y] = dis[x] + z;
				if(++cnt[y] >= n) return 0;
				if(!vis[y]) Q.push(y),vis[y] = 1;
			}
		}
	}
}

 

posted @ 2023-10-12 21:43  LouYW07  阅读(10)  评论(0)    收藏  举报