#include <queue>
#include <utility>
class Solution {
  public:
    /*
        从起点开始,不断选择 当前距离最短且未访问 的节点,把它的邻居的距离更新成更短的值,直到所有节点都确定了最短距离。
        创建邻接表->创建最短距离表、是否遍历过表->创建小根堆->初始化小根堆->循环:提取对顶,更新边能到的节点离起点的最近距离;直到堆为空;
     */

    int findShortestPath(int n, int m, vector<vector<int> >& graph) {
        //邻接表:行号表示起点,pair就是到节点和距离;
        vector< vector< pair<int, int>>> adj(n + 1);
        //初始化邻接表
        for (auto g : graph) {
            int i = g[0]; //起点
            int v = g[1]; //终点
            int w = g[2]; //距离
            adj[i].push_back(make_pair(v, w));  //加入邻接表
        }

        //D杰斯特算法:从起点开始,遍历每个边,更新边能到达的节点的最短距离,对更新了的节点遍历,遍历过了就不用遍历了;
        const int INF = 1e9;
        vector<int> dist(n + 1, INF); //表示从1到i的最短距离,还没有确认最短
        vector<bool> vis(n + 1,
                         false); //vis[i]表示已经遍历过了此节点为起点的边

        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>>
                pq;  //小根堆,存放0到u的目前为止的最短距离,用来遍历节点的下一个边

        dist[1] = 0;
        pq.push({0, 1});

        while (!pq.empty()) {
            auto [d, u] = pq.top();
            pq.pop();  //对这个节点,遍历下边

            if (vis[u]) {
                continue;
            } else {
                vis[u] = true;
            }

            for (auto& edge : adj[u]) { //对以u开头的边遍历,更新
                int w = edge.second;  //距离
                int v = edge.first; //下一个节点

                if (dist[v] > w + d) {
                    dist[v] = d + w; //更新0到v的最短距离
                    pq.push({dist[v], v});  //对到v的最短距离
                }
            }
        }

        // 初始化
        return dist[n] == INF ? -1 : dist[n];
    }
};