AcWing849 Dijkstra求最短路I

给定一个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算法的一般流程是:

  1. 初始化dist[1] = 0,其余结点的dist值为无穷大
  2. 找出一个未被标记的、dist[x]最小的结点x,然后标记x
  3. 扫描结点x的所有出边(x, y, z),若dist[y] > dist[x] + z, 那么使用dist[x]+z来更新dist[y]
  4. 重复上述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());
    
}
posted @ 2019-11-06 23:27  patrolli  阅读(150)  评论(0编辑  收藏  举报