给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值。
请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1。
输入格式
第一行包含整数n和m。
接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z
输出格式
输出一个整数,表示1号点到n号点的最短距离。
如果路径不存在,则输出-1。
数据范围
\(1≤n≤500,\)
\(1≤m≤105,\)
图中涉及边长均不超过10000
输入样例
3 3
1 2 2
2 3 1
1 3 4
输出样例
3
原题链接: https://www.acwing.com/problem/content/851/
用dijkstra算法
解决最短路问题的模板题。dijkstra算法
的一般流程是:
- 初始化
dist[1] = 0
,其余结点的dist
值为无穷大 - 找出一个未被标记的、
dist[x]
最小的结点x
,然后标记x
- 扫描结点x的所有出边
(x, y, z)
,若dist[y] > dist[x] + z
, 那么使用dist[x]+z
来更新dist[y]
- 重复上述2、3步骤,直到所有结点被标记
代码如下:
#include <iostream>
#include <memory.h>
using namespace std;
const int N = 502;
int g[N][N];
int st[N], d[N];
int n, m;
int dijkstra(){
d[1] = 0;
for(int i = 1; i <= n; ++i){
//找到d[]最小的结点
int t = -1; //t记录dist最小的结点
for(int j = 1; j <= n; ++j){
if(!st[j] && (t ==-1 || d[j] < d[t]))
t = j;
}
//从这个结点出发更新其它结点的距离,松弛操作
for(int j = 1; j <= n; ++j){
d[j] = min(d[j], d[t]+g[t][j]);
}
//删除掉这个结点,不再访问它
st[t] = true;
}
//如果结点n的距离为INF,那么就说明不能到达结点n
//否则返回到结点n的距离
if(d[n] == 0x3f3f3f3f) return -1;
else return d[n];
}
int main(){
scanf("%d%d", &n, &m);
memset(g, 0x3f, sizeof(g));
memset(d, 0x3f, sizeof(d));
for(int i = 0; i < m; ++i){
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
if(w < g[a][b]) g[a][b] = w; //选取权重更小的作为两个结点的距离
}
printf("%d", dijkstra());
}