最短路(基础篇)

全源最短路模板

Floyd

我们设 fi,j 表示 ij 的最短路,于是我们枚举中转点 k,就有 fi,jmin(fi,j,fi,k+fk,j)

于是简单枚举一下进行转移即可,时间复杂度 O(n3)

代码:

for(k=1;k<=n;k++){
	for(x=1;x<=n;x++){
		for(y=1;y<=n;y++){
			f[x][y]=min(f[x][y],f[x][k]+f[k][y]);
		}
	}
}

单源最短路模板

单源最短路径

我们考虑一条边 uv,我们尝试进行松弛:disvmin(disv,disu+w(u,v))

于是 BellmanFord(SPFA) 算法所做的,就是尝试不断对每条边进行松弛。每进行一轮循环,就将图上所有的边松弛一次,于是复杂度为 O(nm)

注意:如果一条边被松弛了 n 次及以上,说明图中存在负环

因为 BellmanFord 严格不优于,所以我们给出 SPFA 的实现(只是多了一个队列优化):

int spfa(int S,int T){
	int hh=0,tt=1;
	memset(d,0x3f,sizeof d);
	q[0]=S;st[S]=1;d[S]=0;
	while(hh!=tt){
		int t=q[hh++];
		if(hh==N)hh=0;
		st[t]=0;
		for(int i=h[t];~i;i=ne[i]){
			int j=e[i];
			if(d[j]>d[t]+w[i]){
				d[j]=d[t]+w[i];
				if(!st[j]){
					q[tt++]=j;
					if(tt==N)tt=0;
					st[j]=1;
				}
			}
		}
	}
	return d[T]>=d[0]/2?d[0]:d[T];
}

单源最短路径(强化版)

上述算法会被卡掉,所以我们考虑一种新的最短路算法 dijkstra

我们考虑现在有两个集合,一个是已经确定最短路的 S,剩下的则是 T.

初始化 diss=0,然后从 T 中选取一个最短路长度最小的点,把他移动到 S 中,然后对所有新移动到 S 中的点的出边执行松弛操作。

堆优化代码:

void dijkstra(int s){
  	memset(dis,0x3f,sizeof(dis));
  	dis[s]=0;
  	q.push({0,s});
  	while(!q.empty()){
    	int u=q.top().u;
    	q.pop();
    	if(vis[u])continue;
    	vis[u]=1;
    	for(auto ed:e[u]){
      		int v=ed.v,w=ed.w;
      		if(dis[v]>dis[u]+w){
        		dis[v]=dis[u]+w;
        		q.push({dis[v],v});
      		}
    	}
  	}
}
posted @   zxh923  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示