首页 > 编程语言 >最短路算法

最短路算法

时间:2024-08-18 10:37:38浏览次数:9  
标签:int 短路 源点 算法 edge dp dis

1.Dijkstra算法

算法思想:\(dijkstra\) 算法采用的是贪心的思想。

(1)定义一个\(dis\)数组,\(dis[i]\) 表示i点到源点的最短路径,设源点的 \(dis\) 值为0,其他 \(dis\) 值为 \(∞\) 。

(2)选出其中的最小 \(dis\) 值,进行标记并更新它相邻的 \(dis\) 值。

(3)不断循环操作(2)。

优点:dijkstra 算法可以广泛使用于大多数题目。

缺点: dijkstra 算法不能在图中有负权环时使用。

核心代码:

void dijkstra()
{
    for(int i=1;i<=n;i++)d[i]=INF;
    dis[1]=0;
    for(int i=1;i<=n;i++)
    {
        int mark=-1;
        mindis=INF;
        for(int k=1;k<=n;k++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                if(!vis[edge[j].to]&&edge[j].dis<mindis)
                {
                    mindis=edge[j].dis;
                    mark=edge[j].to;
                }
            }
        }
        vis[mark]=1;
        for(int i=head[mark];i;i=edge[i].nxt)
        {
            if(!vis[edge[i].to])
            {
                d[edge[i].to]=min(d[edge[i].to],d[mark]+edge[i].dis);
            }
        }
    }
}

堆优化:

void dijkstra(int s)
{
	priority_queue<pair<int,int> > q;
	memset(dis,0x3f3f3f3f,sizeof(dis));
	memset(v,0,sizeof(v));
	dis[s]=0;
	q.push(make_pair(0,s));
	while(q.size())
	{
		int x=q.top().second;
		q.pop();
		if(v[x]) continue;
		v[x]=1;
		for(int i=head[x];i;i=edge[i].next)
		{
			if(dis[edge[i].to]>dis[x]+1)
			{
				dis[edge[i].to]=dis[x]+1;
				q.push(make_pair(-dis[edge[i].to],edge[i].to));
			}
		}
	}
}

2. Bellmax-ford算法

(1) 定义一个 \(dis\) 数组,\(dis[i]\) 表示 \(i\) 点到源点的最短路径,设源点的 \(dis\) 值为0,其他 \(dis\) 值为 \(∞\) 。

(2) 从图的任意边开始,对每一条边进行松弛操作(对于边 \(u>v\) ,如果 \(dis[v]>dis[u]+w[u][v]\),\(dis[v]=dis[u]+w[u][v]\) , \(w\) 为图的权值)①,重复点数-1次。

(3)最后再进行一边松弛操作,如果存在①,则存在负权环。
优点:Bellman-ford算法边的权值可以为负数,并可检测负权回路。

缺点:时间复杂度过高。

核心代码:



bool bellman(int v0)    
{
	for(int i=1;i<=nv-1;i++)
	{
		for(int j=1;j<=ne;j++)
		{
			if(dis[edge[j].a]+edge[j].w<dis[edge[j].b])
			{
				dis[edge[j].b]=dis[edge[j].a]+edge[j].w;
			}
                }
		for(int j=1;j<=ne;j++)
		{
			if(d[edge[j].a]+edge[j].w<dis[edge[j].b])
			{
				return 0;
			}
            	}
		return 1;
	}
 }

3.SPFA算法:

算法思想:SPFA算法实际是\(Bellman-ford\)算法的队列优化。

(1) 定义一个\(dis\)数组,\(dis[i]\) 表示i点到源点的最短路径,设源点的 \(dis\) 值为0,其他 \(dis\) 值为 \(∞\) 。定义队列 \(q\) ,源点进队。

(2) 从队列中取出队首元素 \(u\),标记节点 \(u\) 出队,对u相连的所有节点 \(v\) 进行松弛操作。如果松弛成功,检查节点 \(v\) 进队次数,如果超过 \(|V|\),则说明出现负权环,算法结束;否则,修改 \(dis[v]\) ,检查节点 \(v\) 是否在队列中,如果不在,节点 \(v\) 进队。

(3) 重复操作(2)。

优点:可以解决负权环问题。

核心代码:

void spfa(int u)
{
    queue<int> q;   
    q.push(u), dis[u]=0, vis[u]=1;
    while(!q.empty())
    {
        int now=q.front();   
        q.pop();       
        vis[now]=0;      
        for(int i=head[u];i;i=edge[i].next)  
        {
            int v=edge[i].first;          
            if(dis[v]>dis[u]+edge[i].w||dis[v]<0)
            {
            	dis[v]=dis[u]+edge[i].w;
			}
			if(vis[v]==1)
        	{
        	    vis[v]=1;  
        		q.push(v);
        	}
        }   
    }
}

4. Floyd算法

算法思想:Floyd算法是基于动态规划思想的。

(1) 定义 \(dp[k][i][j]\) 表示从点i到点j只允许经过前k个点得到的最短路径。

(2) 如果经过第\(k\)个点,那么 \(dp[k][i][j]=dp[k-1][i][k]+dp[k-1][k][j]\)。

(3) 如果经过第k个点,那么 \(dp[k][i][j]=dp[k-1][i][j]\)。

(4) \(dp[k][i][j]=min(dp[k-1][i][j], dp[k-1][i][k]+dp[k-1][k][j])\)。

(5) 边界:\(dp[0][i][j]=g[i][j],g[i][j]\)指\(i\)到\(j\)的边权,当无法到达时可以设为 \(∞\)。

优点:稠密图效果佳,边权可为负。

核心代码:

memset(dis, 0x7f, sizeof(dis));
for(int i=1;i<=m;i++)
{
    int u, v;
    cin>>u>>v;
   	dis[u][v]=dis[v][u]=w[u][v];
}

for(int k=1;k<=n;k++)
{
    for(int i=1;i<=n;i++)
    {
    	for(int j=1;j<=n;j++)
    	{
    		if((i!=j)&&(i!=k)&&(j!=k))
    		{
    			if(dis[i][j]>dis[i][k]+dis[k][j])
    			{
    				dis[i][j]=dis[i][k]+dis[k][j];
                }
			}
		}
	}
}

标签:int,短路,源点,算法,edge,dp,dis
From: https://www.cnblogs.com/zhouyiran2011/p/18365138

相关文章

  • 算法刷题记录 八十五【图论的广度优先搜索理论基础】
    前言图论章节第2篇。第1篇:记录八十二【图论理论基础及深度优先搜索算法】;本文:记录八十五【图论的广度优先搜索理论基础】一、广度优先搜索理论基础广度优先搜索理论基础参考链接1.1知识点框架1.2模拟广度搜索的过程在有向图中,以下图为例,如何进行广度优先搜索......
  • 24/8/18算法笔记 MBPO算法
    MBPO(Model-BasedPolicyOptimization)是一种先进的强化学习算法,它结合了模型预测和策略优化的思想来提高学习效率和性能。这种算法特别适用于连续动作空间的问题,它通过建立一个环境的动态模型来进行模拟预测,并利用这些预测来改进策略。MBPO的核心包括以下几个步骤:模型学习:通......
  • Twenty Lectures on Algorithmic Game Theory 算法博弈论二十讲 Lecture 2 Mechanism
    TwentyLecturesonAlgorithmicGameTheory算法博弈论二十讲Lecture2MechanismDesignBasics过去的15年里,计算机科学与经济学之间进行了活跃的互动,催生了算法博弈论这一新兴领域。许多现代计算机科学中的核心问题,从大规模网络中的资源分配到在线广告,都涉及多个自......
  • 手把手教你利用算法工具链训练、量化、编译、可视化征程 6 参考算法 BEVFormer
    写在前面:关于OE包内参考算法的使用,地平线已经释放了大量文档指导用户完成各类模型的训练、校准、量化、定点过程,但其中有些细节可能会对不是特别熟悉算法工具链的客户造成困扰,本文档致力于消除参考算法使用过程中所有可能存在的模糊操作,引导初学者快速上手参考算法,在实操中树立......
  • C++做算法题,容器知识看这一篇就够啦!
    C++常用容器分享(算法题,掌握这些就够了)vector是什么连续的顺序存储结构,其实就是一个可变数组想使用的话记得#include<vector>怎么用初始化语法vector<类型>名字(长度,初始值)演示一下//一维的vectorvector<int>arr;//不指定里面有多少个元素vector<int>a......
  • 使用贝叶斯优化CDENCLUE聚类算法参数
    目录1.贝叶斯优化的基本原理原理和实现步骤:2.轮廓系数的原理公式:3.贝叶斯优化的实现流程(伪代码)1.贝叶斯优化的基本原理贝叶斯优化是一种基于概率模型的优化方法,主要用于优化计算代价高昂的黑盒函数。它结合了先验知识和观察到的数据来更新后验知识,并用一个易......
  • 二分查找不理解?一篇弄懂!--基础二分查找算法详细解释(带简单例题的详细解法)
    本文参考:灵茶山艾府分享丨【题单】二分算法(二分答案/最小化最大值/最大化最小值/第K小)-力扣(LeetCode)二分查找红蓝染色法_哔哩哔哩_bilibili本文主要详细讲解基础的二分算法中的查找,包括原理和模板,并用leetcode和洛谷的一些例题来进行实际题目讲解,如果觉得有帮助或者写......
  • 以node / link文件表征的道路网络-----dijkstra算法yyds-----基于南京公路公开数据做
    前文已经基于公开数据,获得了南京的全域高速公路的路网数据,这些以node/link文件表征的道路网络不仅延续了osm地图中所包含的经纬度、名称、容量等信息,还包含了一个重要的道路等级字段“link_type_name”。交通部门一般以高速公路、国省干道、城市道路、乡道农路作为区分......
  • 二分查找(算法详解+模板+例题)
    一.二分的定义二分法(Bisectionmethod)即一分为二的方法.设[a,b]为R的闭区间.逐次二分法就是造出如下的区间序列([an,bn]):a0=a,b0=b,且对任一自然数n,[an+1,bn+1]或者等于[an,cn],或者等于[cn,bn],其中cn表示[an,bn]的中点。二.基本思路1.将数组排序。2.一直将数组除以二,直到找到那......
  • 数据结构与算法——BFS(广度优先搜索)
    算法介绍:广度优先搜索(Breadth-FirstSearch,简称BFS)是一种遍历或搜索树和图的算法,也称为宽度优先搜索,BFS算法从图的某个节点开始,依次对其所有相邻节点进行探索和遍历,然后再对这些相邻节点的相邻节点进行探索,直到遍历完所有的节点。BFS算法使用队列来辅助实现,将起始节点放入队列......