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;
}