一、引言
图论中经常出现找最短路问题
有一种贪心算法可以找到最短路,这就是Dijkstra算法
二、思想
Dijkstra有一个优点,就是在正边权连通图中可以保证找到最短路,且时间复杂度为O(n*n)
代码整体逻辑:先建立一个数组,表示起点到这个点的最短距离,并将除自己到自己以外的所有值都设为0x3f3f3f3f,先找到离起点最近的点,然后用这个点去更新其他所有点
核心代码:
找最近点部分:
int t = -1;
for(int i = 1; i <= n; i++)
{
if(!st[i] && (t == -1 || dist[t] > dist[i]))
{
t = i; //找到了离起点最近的点
}
}
if(t == -1) //当所有点都遍历过了
{
return ;
}
更新距离部分:
st[t] = 1;
for(int i = 1; i <= n; i++)
{
if(dist[t] + graph[t][i] < dist[i]) // dist[t] 表示 1 -> t 的最短距离 1 -> t + t - > i 1 -> i
{
dist[i] = dist[t] + graph[t][i]; // 如果还没被更新或原距离更远,则更新其距离
}
}
三、完整代码
#include<iostream>
#include<cstring>
using namespace std;
const int N = 505;
int graph[N][N], st[N], dist[N]; //用邻接矩阵存图
int m, n;
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for(int j = 0; j < n; j++)
{
int t = -1;
for(int i = 1; i <= n; i++)
{
if(!st[i] && (t == -1 || dist[t] > dist[i]))
{
t = i; //找到了离起点最近的点
}
}
if(t == -1) //当所有点都遍历过了
{
return ;
}
st[t] = 1;
for(int i = 1; i <= n; i++)
{
if(dist[t] + graph[t][i] < dist[i]) // dist[t] 表示 1 -> t 的最短距离 1 -> t + t - > i 1 -> i
{
dist[i] = dist[t] + graph[t][i]; // 如果还没被更新或原距离更远,则更新其距离
}
}
}
}
int main()
{
cin>>n>>m;
memset(graph, 0x3f, sizeof graph);
for(int i = 0; i < m; i++)
{
int a, b, c;
cin>>a>>b>>c;
graph[a][b] = min(graph[a][b], c); //重边时取最小值
}
dijkstra();
if(dist[n] != 0x3f3f3f3f) cout<<dist[n]; //可以到达终点
else cout<<-1; //不能到达终点
}