(C++)最短路径(Dijkstra算法,最详尽代码注释)

写在所有的前面:

本文采用C++实现代码

题目说明

题目:最短路径

题目出处

广西大学oj
22级《算法设计与分析》第三次课堂作业
链接:https://oj.gxu.edu.cn/contest/626/problem/0003

题目描述Description

给出一个有向图(无负权值),求任意两点间的最短路径

输入Input

第一行为有向图中点的数量n(各点从0到n-1编号)
第二行为边的数量 m
第三行为要求其间最短路径的两个点
第四行起为m条边的信息,包括起点、终点和路径长度(保证长度是整数,且绝对值不大于100)
以空格隔开

输出Output

求出输入中第三行两个点之间的最短路径长度并输出

样例Sample

输入

8
15
0 5
4 5 35
5 4 35
4 7 37
5 7 28
7 5 28
5 1 32
0 4 38
0 2 26
7 3 39
1 3 29
2 7 34
6 2 40
3 6 52
6 0 58
6 4 93

输出

73

限制Hint

保证n小于1000,且答案不超过 10^5.

解答说明

方案1:Dijkstra算法

解题思路

一般情况
  1. 遍历边,寻找最小费用结点(不在路径内)
  2. 将最小结点加入最短路径
  3. 更新其带来的改变(相邻点最小费用记录)
特殊情况
  1. 初始化:总起点作为路径起点并更新最小费用记录
  2. 未找到可用结点(无法生成最短路径)

代码实现

#include<iostream>

using namespace std;

//Dijkstra最短路径算法
const int N = 1010, MAXVALUE = 1e5 + 10;
int n, m, a, b;// 结点数,边数,总起点,总终点
int w[N][3];// 边 w[i][0] 费用,w[i][1] 起点,w[i][2] 终点
int min1[N][2];// min[i][0] 结点 a 到 i 最小费用,min[i][1] 结点是否已被计算入最短路径 是 1 / 否 0

int main()
{
	scanf("%d", &n);
	scanf("%d", &m);
	scanf("%d%d", &a, &b);

	//题目要求 i 从 0 开始,共 n 个结点
	for (int i = 0; i < n; i++) min1[i][0] = MAXVALUE;//结点 a 到 i 最小费用初始化为无穷大

	//输入边
	for (int i = 0; i < m; i++)
	{
		scanf("%d%d%d", &w[i][1], &w[i][2], &w[i][0]);
	}

	//最短路径寻找

	//将 a 结点作为路径起点
	min1[a][0] = 0, min1[a][1] = 1;
	//更新 min
	for (int i = 0; i < m; i++)//每一条边
	{
		if (w[i][1] == a)// a 结点作为边的起点
			min1[w[i][2]][0] = w[i][0];// 将该边费用定为 a 到该边终点 w[i][2] 结点的最小费用
	}

	//插入其他结点
	for (int i = 0; i < n - 1; i++)//最多选择 n - 1 次结点
	{
		//寻找最小费用结点
		int p = -1, pmin = MAXVALUE;//最小费用边指针,最小费用
		for (int j = 0; j < m; j++)//遍历每一条边
		{
			if (min1[w[j][2]][0] < pmin && min1[w[j][2]][1] == 0)// a 到该边终点费用更小 且 终点不在路径内
			{
				p = j;//更新最小费用边指针
				pmin = min1[w[j][2]][0];//更新最小费用
			}
		}

		//未找到可用结点,即无法生成最短路径
		if (pmin == MAXVALUE)
		{
			printf("Imp");
			return 0;
		}

		// b 结点为最小结点
		if (w[p][2] == b)
		{
			printf("%d", pmin);
			return 0;
		}

		//将最小结点加入最短路径
		min1[w[p][2]][1] = 1;
		//更新 min
		for (int j = 0; j < m; j++)//每一条边
		{
			if (w[j][1] == w[p][2] && pmin + w[j][0] < min1[w[j][2]][0])// 边的起点为所求最小结点 且 起点最小费用 + 边费用 小于 终点的最小费用
				min1[w[j][2]][0] = pmin + w[j][0];// 更新终点 w[i][2] 结点的最小费用
		}
	}

	return 0;
}

其他解释

floyd 算法待写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值