首页 > 其他分享 >最短路(floyd,dijkstra,spfa)

最短路(floyd,dijkstra,spfa)

时间:2025-01-17 20:54:03浏览次数:1  
标签:int dijkstra len vis spfa floyd push dis

最短路

[floyd]
思考枚举k作为中转点来进行赋最小值,
原转移为a[k][i][j]=min(a[k][i][j],a[k-1][i][k-1],a[k-1][k-1][j]);
经空间压缩后为a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
注:为多远最短路 
核心代码:
void floyd(){
	for(int k=1;k<=n;k++){
	    for(int i=1;i<=n;i++){
	        for(int j=1;j<=n;j++){
	            a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
	        }
	    }
	} 
}
[dijkstra]
一种基于贪心的算法,每次弹出堆中的点,
对所有与其相连的点进行松弛操作,
然后将松弛成功且还未以其作为松弛起点的点加入堆,
准备下一次松弛。
(松弛,即查看以当前节点为中转点的最短路是否比目标节点的最短路小,小即更新)
注:无法处理负权 
核心代码:
typedef pair<int,int> P;
struct node{
	int to,len;
};
//dis为最短路径,mp为临接表,vis为标记数组
void dijkstra(int s){
	priority_queue<P,vector<P>,greater<P> >q;
	dis[s]=0;
	q.push(P{dis[s],s});
	while(!q.empty()){
		int l=q.top().second;
		q.pop();
		if(vis[l]){
			continue;
		}
		vis[l]=1;
		for(auto v:mp[l]) {
			if(dis[v.to]>dis[l]+v.len){
				dis[v.to]=dis[l]+v.len;
				q.push(P{dis[v.to],v.to});
			}
		}
	}
} 
[spfa]
每次弹出队列中的点对周围进行松弛操作,
将松弛成功的点加入队列(不论是否其已经为松弛起点过),
一直执行到没有点可以松弛。
所以spfa可以处理负权环,当一个点被松弛了n次及以上说明该处有负权环。
核心代码:
struct node{
	int to,len;
};
//数组意思同上 
void spfa(int s){
	queue<int>q;
	dis[s]=0;
	vis[s]=1;
	q.push(s);
	while(!q.empty()){
		int l=q.top();
		q.pop();
		vis[l]=0;
		for(auto v:mp[l]){
			if(dis[v.to]>dis[l]+v.len){
				dis[v.to]=dis[l]+v.len;
				if(!vis[l]){
					q.push(v.to);
					vis[l]=1;
				}
			}
		}
	}
}
1.
accoders【一本通图 最短路径算法】 信使 2004
思路:
打一个dijkstra的板子,注意是无向图。
code:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
struct node{
	int to,len;
};
vector<node>mp[10010];
int dis[10010],vis[10010];
void dij(int s){
	priority_queue<P,vector<P>,greater<P> >q;
	dis[s]=0;
	q.push(P{dis[s],s});
	while(!q.empty()){
		int l=q.top().second;
		q.pop();
		if(vis[l]){
			continue;
		}
		vis[l]=1;
		for(auto v:mp[l]){
			if(dis[v.to]>dis[l]+v.len){
				dis[v.to]=dis[l]+v.len;
				q.push({dis[v.to],v.to});
			}
		}
	}
}
int main(){
	memset(dis,0x3f3f3f,sizeof dis);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int l,r,w;
		cin>>l>>r>>w;
		mp[l].push_back({r,w});
		mp[r].push_back({l,w});
	}
	dij(1);
	int ans=-1;
	for(int i=1;i<=n;i++){
		ans=max(ans,dis[i]);
	}
	if(ans>=0x3f3f00){
		cout<<-1;
	}else{
		cout<<ans;
	}
	int _=0;
	return (_^_^_);
}
2.
accoders 【一本通提高篇SPFA算法的优化】Wormholes 虫洞2117
思路:
用spfa判断负环。
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1000010,inf=0x3f3f3f3f;
int T;
int n,m,k;
int num[N],dis[N],vis[N];
struct node{
	int to,len;
};
vector<node>e[N];
void init(){
	memset(dis,inf,sizeof dis);
	memset(num,0,sizeof num);
	memset(vis,0,sizeof vis);
	for(int i=1;i<=n;i++){
		e[i].clear();
	}
}
int spfa(int s){
	queue<int>q;
	dis[s]=0;
	q.push(s);
	vis[s]=1;
	num[s]=1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(auto v:e[u]){
			if(dis[v.to]>dis[u]+v.len){
				dis[v.to]=dis[u]+v.len;
				if(!vis[v.to]){
					num[v.to]++;
					if(num[v.to]>n-1){
						return 0;
					}
					q.push(v.to);
					vis[v.to]=1;
				}
			}
		}
	}
	return 1;
}
int main(){
	cin>>T;
	while(T--){
		cin>>n>>m>>k;
		init();
		for(int i=1;i<=m;i++){
			int u,v,w;
			cin>>u>>v>>w;
			e[u].push_back({v,w});
			e[v].push_back({u,w});
		}
		for(int i=1;i<=k;i++){
			int u,v,w;
			cin>>u>>v>>w;
			e[u].push_back({v,-w});
		}
		if(spfa(1)){
			cout<<"NO\n";
		}else{
			cout<<"YES\n";
		}
	}
	return 0;
}
 
 

标签:int,dijkstra,len,vis,spfa,floyd,push,dis
From: https://www.cnblogs.com/123lbh321/p/18677648

相关文章

  • 搜索与图论(二)-最短路问题(dijkstra、Bellman-Ford、SPFA、Floyd)
    目录一、单源最短路问题 1.朴素dijkstra算法O(n²) 2.堆优化Dijkstra算法O(mlogn)3.Bellman-Ford算法O(nm)4.SPFA算法 O(m)/O(nm)应用-判断负环 二、多元最短路问题O(n³)Floyd算法 一、单源最短路问题 问题定义:1.朴素dijkstra算法O(n²)适用于......
  • 【一看就会】路径规划算法【一】——广度优先,深度优先,Dijkstra、A*、D*
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、输入输出1.输入环境约束条件目标其他2.输出二、广度优先搜索——BFS三、深度优先搜索——DFS四、Dijkstra五、A*六、D*1.初始路径规划(环境未变化)2.环境变化3.动态调整1.受影响节点标记2......
  • 探讨人工智能机器人学之路径规划与导航:A*算法、Dijkstra算法等路径规划方法
    引言在人工智能(AI)和机器人学中,路径规划与导航是一个至关重要的课题。机器人在复杂的环境中,必须能够根据环境信息和目标要求,自动计算一条从起始位置到目标位置的最优或可行的路径。路径规划不仅仅是关于如何找到目标位置,还涉及如何在多变、动态的环境中避免障碍、实现效率和安......
  • dijkstra算法
      Dijkstra算法是用于计算图中单源最短路径的经典算法,其核心思想是贪心算法,通过不断选择当前距离源点最近的节点,更新源点到其他节点的距离,直到所有节点都被访问过。算法步骤初始化:设源点为s,定义一个数组dist[]来存储从源点s到各个顶点的最短距离,初始时,源点s到自身的......
  • Floyd算法
    关于Floyd算法的优化思路,因为dist[i][j]和dist[j][i]是对称的,在遍历的时候我们可以让k从0开始,i从0到k,j从k到n。在初始化dist的时候我们首先比较两个地点的大小,然后从小的向大的方向修路。最后接收st和ed的时候也是比较大小,从小的向大的出发。#include<stdio.h>#include<s......
  • 求单源最短路的Dijkstra算法
    请编写程序,实现在带权的有向图中求单源最短路的Dijkstra算法。注意:当多个待收录顶点路径等长时,按编号升序进行收录。输入格式:输入首先在第一行给出两个正整数,依次为当前要创建的图的顶点数n(≤100)和边数m。随后m行,每行给出一条有向边的起点编号、终点编号、权重。顶点编......
  • Bellman-Ford\SPFA单源最短路算法
    Bellman-Ford单源最短路算法不采用SPFA实现的Bellman-Ford算法"题目中的图没有特殊性质时,若SPFA是标算的一部分,题目不应当给出Bellman–Ford算法无法通过的数据范围"Bellman-Ford的原理如下先枚举节点,在枚举边,每进行一轮循环,对图上所有的边都尝试进行一次松弛操作,当......
  • 代码随想录算法训练营第六十天|Bellman_ford队列优化法(SPFA)、bellman_ford之判断负
    前言打卡代码随想录算法训练营第49期第六十天(づ◕‿◕)づ首先十分推荐学算法的同学可以先了解一下代码随想录,可以在B站卡哥B站账号、代码随想录官方网站代码随想录了解,卡哥清晰易懂的算法教学让我直接果断关注,也十分有缘和第49期的训练营大家庭一起进步。Bellman_ford队......
  • 代码随想录算法训练营第五十九天|dijkstra(堆优化版)精讲、Bellman_ford
    前言打卡代码随想录算法训练营第49期第五十九天⚆_⚆(˘❥˘)(•̀⌓•)シ(人•͈ᴗ•͈)♡♡首先十分推荐学算法的同学可以先了解一下代码随想录,可以在B站卡哥B站账号、代码随想录官方网站代码随想录了解,卡哥清晰易懂的算法教学让我直接果断关注,也十分有缘和第49期的......
  • Dijkstra单源最短路堆优化算法
    Dijkstra单源最短路堆优化算法使用基于堆的优先队列,我们可以在进行松弛操作前对找边进行优化操作时间复杂度为\(O(m\logm)\),其中\(m\)为边的数量,优先队列找边的时间复杂度为\(O(\logm)\)优先队列默认为一个大根堆,即堆顶的元素的优先级最高,体现在某个变量的值上每次从队......