给定一个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()); }