Dijkstra求最短路

本文详细介绍了Dijkstra算法的基本原理和步骤,通过举例解释了如何找到图中两点间的最短路径。同时,文章还探讨了算法的代码实现,包括标准版本和堆优化版本,强调了初始化、选择最短路径和更新路径的重要性。堆优化版利用小根堆提高效率,动态维护最短路径。
摘要由CSDN通过智能技术生成

首先要明白这个算法的原理:

如图:找v0到v6的最短路径。
在这里插入图片描述
在找最短路之前先画一个表格:vj代表这一轮选出的最短路径,距离就是最短距离。
在这里插入图片描述
无法到达用INF(无穷)表示

具体寻找步骤:

i=1:v1 = 13 , v2 = 8 , v3 = INF , v4 = 30 , v5 = INF , V6 = 32 这一轮选出的最短距离为v2 = 8。
i=2: 既然v2是最短路那么从v2走到的点(可能更短)也被记录(每轮选出的最短路都可用)
注意这里v2已被选出是最短路则不更新。
v1 = 13 , v3 = (8 + 5)(通过v2的点) , v4 = 30 , v5 = INF , V6 = 32
注意 : 如果某点可以通过多个点到达,选择最短的一条。

最终表格
在这里插入图片描述
算法总结

1.初始化:先找出从v0到到各点的直达路径(通过一条弧到达的路径)。
2.选择:从这些路径找出最短的路径。
3.更新:通过找到的最短路能否更新其他路。

选择代码实现

// dis表示到起点路径
for (int j = 1; j <= n; j++)
{
	if (dis[j] < dis[t]) t = j; // 遍历整个路径选出最短路的点t
}

更新代码实现

//g[t][j]表示t到j的路径大小
for (int j = 1; j <= n; j++)
{
	dis[j] = min(dis[j], dis[t] + g[t][j]); //通过找到的最短路能否更新其他路
}

Dijkstra求最短路代码

void dijkstra()
{
	memset(dis, 0x3f, sizeof dis); // 初始化距离为无穷 
	dis[1] = 0; // 初始化为了找出从起点到各点的直达路径
	for (int i = 0; i < n; i++)
	{
		int t = 0; // 保证t每次都被更新dis[t] = 无穷
		for (int j = 1; j <= n; j++)
		{
			if (!vis[j] && dis[j] < dis[t]) t = j; // 遍历整个路径选出最短路
		}
		vis[t] = true; // 该点已是最短路,不在更新
		for (int j = 1; j <= n; j++)
		{
			dis[j] = min(dis[j], dis[t] + g[t][j]); //通过找到的最短路能否更新其他路
		}
	}
}

堆优化

思路

思路与上面一样,只不过选择是用堆来实现。
1.初始化
2.选择:将被更新的路入队比较,选择队中的最短路(小根堆的堆顶)。
3.更新:通过找到的最短路能否更新其他路,将更新后的路径入队来取代堆中原来该路的路径。
(堆不能删除,但可以比较,更新后会在原路径上面,达到了取而代之的作用)。

int dijkstra()
{
	priority_queue<PII, vector<PII>, greater<PII>> heap; // 定义小根堆
	memset(dis, 0x3f, sizeof dis); // 初始化距离为无穷
	heap.push({ 0,1 }); // 从1结点开始做初化
						// 堆存结点和该结点到1的距离
						// 堆是先按第一个数排序,所以第一存距离
						// pair<结点到1的距离 ,结点>
	while (heap.size())
	{
		auto t = heap.top(); heap.pop(); // 队头一定是最短路经
		int d = t.first, v = t.second;
		if (vis[v]) continue; // 防止重边情况
		vis[v] = true; // 第一次一定是该点最短路
		for (int i = h[v]; i != -1; i = ne[i])
		{
			int j = e[i];
 			if (dis[j] > d + w[i]) //通过找到的最短路能否更新其他路
			{
				dis[j] = d + w[i]; // 更新到j的最短路
				heap.push({ dis[j], j }); // 将该条路入队
			}
		}
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值