首页 > 编程语言 >算法之Floyd-Warshall算法【c++】【图论】【最短路】

算法之Floyd-Warshall算法【c++】【图论】【最短路】

时间:2023-01-01 14:34:15浏览次数:60  
标签:Warshall 短路 c++ int 算法 maxn 节点 dis

我们作为刚学图论的小蒟蒻,先接触到的算法一定是图上最短路径算法。而最短路算法中最简单的当属Floyd-Warshall算法。下面是一些基本介绍:

​该算法可以计算图上任意两点间的最短路径
时间复杂度:​​​​O(n^3)
适用情况:适用出现负边权的情况

算法伪代码:

弗洛伊德算法的基本思想是动态规划,我们枚举每一个点,并以其为中间节点更新任意两点间的最小距离,伪代码:

#define maxn 最大节点数
#define inf 0x7fffffff-2
long long val[maxn][maxn];
long long dis[maxn][maxn];
inline void floyd(){
    for(int i=1;i<=maxn;i++)
    	for(int j=1;j<=maxn;j++)
    		if(val[i][j])
    			dis[i][j]=val[i][j];
			else
				dis[i][j]=inf;
	for(int k=1;k<=maxn;k++)
		for(int i=1;i<=maxn;i++)
			for(int j=1;j<=maxn;j++)
				if(dis[i][j]>dis[i][k]+dis[k][j])
					dis[i][j]=dis[i][k]+dis[k][j];
}

​此时,dis[i][j]就是从i节点到j节点的最短路径。

算法分析&&思路讲解

  1. 初始化:我们在初始化时,将有边相连的节点间distance更新为边权值,无边相连直接设为极大值。
  2. 动态规划:对于每个节点,我们都让它做一次中间节点(k),然后分别枚举另外两个节点(i,j),如果当前从i到j的最短路大于从i到k的最短路加上从j到k的最短路,即从i到j如果经过k点会路径更短,那么我们更新从i到j的最短路。
  3. 算法结束,我们得到了所有的最短路。

需要强调的一点是,floyd中k的循环必须写在最外层,否则会导致动态规划状态转移发生错误!

例题讲解:Luogu P2935

传送门
不难发现,题目是让我们求所有牧场到喜欢的牧场的最短路,这就是所谓的多源最短路问题。对于这道题思路如下:

  1. 用floyd求出所有最短路。
  2. 枚举每个点,求出最小平均距离。

该题数据较小,这种思路完全可以通过。
代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3fffffff
int n,m,f,u,v,t;
int square[501][501];
long long dis[501][501];
int like[501];
int main(){
	scanf("%d %d %d",&n,&f,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			dis[i][j]=inf;
		}
		dis[i][i]=0;
	}//预处理。
	for(int i=1;i<=f;i++){
		scanf("%d",&like[i]);
	}//输入每个喜欢的牧场
	for(int i=1;i<=m;i++){
		scanf("%d %d %d",&u,&v,&t);
		dis[u][v]=t;
		dis[v][u]=t;
	}//输入牧场距离并预处理
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);//裸的floyd板子
			}
		}
	}
	int ans,maxx=inf,sum=0;
	for(int i=1;i<=n;i++){
		sum=0;
		for(int j=1;j<=f;j++){
			sum+=dis[i][like[j]];//统计从该节点到所有喜欢的牧场的总最短距离
		}
		if(sum<maxx){
			ans=i;
			maxx=sum;
		}
        //这里注意一下,题目说让我们求的是平均距离最小,但其实喜欢的牧场个数固定,我们就只需要求总最短路径最小就行了,不用再取平均值。
	}
	cout<<ans;//输出牧场序号
	return 0;
}

拓展延伸:算法变形

floyd算法在一些情况下可以变形,用途是判断图上任意两点间连通性。
伪代码:

#define maxn 最大节点数
bool val[maxn][maxn];
bool dis[maxn][maxn];
inline void floyd(){
    for(int i=1;i<=maxn;i++)
    	for(int j=1;j<=maxn;j++)
    		if(val[i][j])
    			dis[i][j]=1;//相邻两点间距离设为ture
			else
				dis[i][j]=0;//不相邻设为false
	for(int k=1;k<=maxn;k++)
		for(int i=1;i<=maxn;i++)
			for(int j=1;j<=maxn;j++)
				dis[i][j]=dis[i][j]||(dis[i][k]&&dis[k][j]);
                //原理:若i与k联通,k与j联通,则i与j联通
}

完结撒花

标签:Warshall,短路,c++,int,算法,maxn,节点,dis
From: https://www.cnblogs.com/mornhus-xsylf-123/p/17018055.html

相关文章

  • C++ | 2-移动
    如何实现移动有分开的拷贝构造和移动构造函数。有swap成员函数,支持和另外一个对象快速交换成员。你的对象的名空间下,应当有一个全局的swap函数,调用成员函数swap来......
  • C++公司员工考勤管理系统[2023-01-01]
    C++公司员工考勤管理系统[2023-01-01]题目15“公司员工考勤管理系统设计”1、问题描述某公司需要存储雇员的编号、姓名、性别、所在部门,级别,并进行工资的计算。其中,雇......
  • 面试笔试刷题 C++ (持续更新)
    阅读C++语言代码输出()​​int​​​​main()​​​​{​​​​int​​​​arr[]={​​​​1​​......
  • OpenCV+yolov3实现目标检测(C++,Python)
    OpenCV+yolov3实现目标检测(C++,Python)  目标检测算法主要分为两类:一类是基于RegionProposal(候选区域)的算法,如R-CNN系算法(R-CNN,FastR-CNN,FasterR-CNN),它们是two-st......
  • C++用finally函数实现当前函数运行结束自动执行一段代码
    我们的需求可能有这样的需求,fun(){    xx;    xx;    xx;    //希望在这里能自动执行一段设定好的代码,实现一些自动清除啥啥啥的操作}核心......
  • 聚类算法-最大最小距离算法(实例+代码)
    聚类算法-最大最小距离算法(实例+代码)目录​​聚类算法-最大最小距离算法(实例+代码)​​​​一、最大最小距离算法基本思想​​​​二、算法实现步骤​​​​1.最大最小距......
  • 一文详尽之支持向量机算法!
     Datawhale干货 作者:小一,Datawhale优秀学习者寄语:本文介绍了SVM的理论,细致说明了“间隔”和“超平面”两个概念;随后,阐述了如何最大化间隔并区分了软硬间隔SVM;同时,介绍了SV......
  • SVM算法在项目实践中的应用!
     Datawhale干货 作者:苏丽敏,Datawhale优秀学习者,北理工计算机硕士支持向量机(SupportVectorMachine)是Cortes和Vapnik于1995年首先提出的,它在解决小样本、非线性及高维模......
  • 122FPS、51.8mAP 超轻量关键点检测算法PP-TinyPose来啦!
    精准的人机交互任务,如手势控制、智能健身、体感游戏等,背后的核心技术是什么?那必须是关键点检测!还有智慧城市、智慧安防等领域的打架斗殴、司机/工人违规操作等异常行为识别,......
  • 机器学习中的优化算法!
     Datawhale干货 作者:李祖贤,Datawhale高校群成员,深圳大学在机器学习中,有很多的问题并没有解析形式的解,或者有解析形式的解但是计算量很大(譬如,超定问题的最小二乘解),对于此类......