Dijkstra算法图文详解(转)

Dijkstra算法

Dijkstra算法算是贪心思想实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。

问题引入:

指定一个点(源点)到其余各个顶点的最短路径,也叫做“单源最短路径”。例如求下图中的1号顶点到2、3、4、5、6号顶点的最短路径。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面我们来模拟一下:
在这里插入图片描述
在这里插入图片描述
代码实现:

#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;

int ma[1005][1005];
int dis[1005];
bool vis[1005];
int t, n;

void init()
{
	//初始化ma数组
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			ma[i][j] = i == j ? 0 : INF;
	//初始化vis数组
	memset(vis, 0, sizeof(vis));
	vis[n] = 1;
}

void Dijk()
{
	for (int i = 0; i < n - 1; i++)//遍历除了n本身以外的n-1个城市,这里的i不代表城市,仅代表遍历n-1次
	{
		int min = INF, k;//k用来存储最小的且没被松弛过的城市
		for (int j = 1; j <= n; j++)
		{
			if (min > dis[j] && !vis[j]) //依次比较
			{
				min = dis[j];
				k = j;//记录最小且没被松弛过的城市的下标
			}
		}
		vis[k] = 1;//标记被松弛过的城市
		for (int h = 1; h <= n; h++)
		{
			if (dis[h] > dis[k] + ma[k][h])
				dis[h] = dis[k] + ma[k][h];
		}
	}	
}

int main(void)
{
	scanf("%d%d", &t, &n);
	init();
	int a, b, c;
	while (t--)
	{
		scanf("%d%d%d", &a, &b, &c);
		if (ma[a][b] > c)//可能会有已经有的路径长度,但是新的长度大于原有的,所以需要判断
			ma[a][b] = ma[b][a] = c;
	}
	for (int i = 1; i <= n; i++)//初始化dis数组
		dis[i] = ma[n][i];
	Dijk();
	if (dis[1] == INF)
		printf("-1\n");
	else
		printf("%d\n", dis[1]);
	return 0;
}
发布了162 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43772166/article/details/88783090