Problem p02868 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <cmath>
#include <fstream>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <unordered_set>
#include <vector>

#define MOD_BIG 1000000007
#define MOD_BIG2 998244353
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::string;
using ll = long long;
using pint = std::pair<int, int>;
using pll = std::pair<ll, ll>;
using std::vector;

#define FOR(i, begin, end)                                                     \
  for (int i = (begin), i##_end_ = (end); i < i##_end_; i++)
#define IFOR(i, begin, end)                                                    \
  for (int i = (end)-1, i##_begin_ = (begin); i >= i##_begin_; i--)
#define REP(i, n) FOR(i, 0, n)
#define IREP(i, n) IFOR(i, 0, n)

//////////////////////////////////////

enum Status {
  Not = 0,
  Now,
  End,
};

template <typename T> struct Edge {
  int to;
  int from;
  T weight;
  Edge(int from, int to, T weight) : from(from), to(to), weight(weight) {}
};

template <typename T, typename D> struct Graph {
  int n;
  vector<vector<Edge<T>>> g;
  vector<D> data;
  vector<Status> s;

  Graph(int N) : n(N), g(N + 1), data(N + 1), s(N + 1) {}

  void add_edge(int from, Edge<T> e) { g[from].push_back(e); }
  void add_edge(int from, int to, T weight) {
    g[from].push_back(Edge<T>(from, to, weight));
  }
  void set_data(int node, D value) { data[node] = value; }

  // 幅優先探索による最短経路
  // weightが全て同一の場合線形
  std::pair<vector<T>, vector<vector<Edge<T>>>> bfs_spp(int start) {
    vector<T> d(n + 1, -1);
    vector<vector<Edge<T>>> route(n + 1);
    std::queue<int> q;
    d[start] = 0;
    q.push(start);
    while (!q.empty()) {
      int v = q.front();
      q.pop();

      for (auto e : g[v]) {
        if (d[e.to] != -1 && d[e.to] != 0) {
          // 到達済み
          continue;
        }
        d[e.to] = d[e.from] + 1;
        auto tmp = route[e.from];
        tmp.push_back(e);
        route[e.to] = tmp;
        q.push(e.to);
      }
    }
    return std::make_pair(d, route);
  }

  // ダイクストラ法
  // weightが非負の場合の最短経路
  // 経路が存在しない場合、INFが返るのでオーバーフローに注意
  std::pair<vector<T>, vector<vector<Edge<T>>>> dijkstra(int start) {
    using P = std::pair<T, int>;
    std::priority_queue<P, vector<P>, std::greater<P>> que;
    T T_MAX = std::numeric_limits<T>::max();
    vector<T> d(n + 1, T_MAX);
    vector<vector<Edge<T>>> route(n + 1);
    d[start] = 0;
    que.push(P((T)0, start));
    while (!que.empty()) {
      P p = que.top();
      que.pop();
      int v = p.second;
      if (d[v] < p.first)
        continue;
      for (Edge<T> e : g[v]) {
        if (d[e.to] > d[v] + e.weight) {
          d[e.to] = d[v] + e.weight;
          auto tmp = route[e.from];
          tmp.push_back(e);
          route[e.to] = tmp;
          que.push(P(d[e.to], e.to));
        }
      }
    }
    return std::make_pair(d, route);
  }

  // ベルマン-フォード法
  // weightを負を含む距離として最短経路を求める
  // 無限ループが存在する場合、trueを1つ目に返す
  std::pair<bool, vector<T>> bellman_ford(int start) {
    T T_INF = std::numeric_limits<T>::max();
    vector<T> d(n + 1, T_INF);
    vector<Edge<T>> E;
    for (int i = 0; i <= n; i++) {
      for (auto e : g[i]) {
        E.push_back(e);
      }
    }
    d[start] = 0;
    for (int i = 0; i <= n; i++) {
      for (auto e : E) {
        if (d[e.from] != T_INF && d[e.from] + e.weight < d[e.to]) {
          // 最初or別のstartからe.toへの最短路を発見
          d[e.to] = d[e.from] + e.weight;
          // std::cout << "new route find, to: " << e.to << ", distance: " <<
          // d[e.to] << std::endl;
          if (i == n) {
            // もう全ての辺はチェック済みのはずなのにまだ更新がある：無限ループあり
            return std::make_pair(true, d);
          }
        }
      }
    }
    return std::make_pair(false, d);
  }

  // あるノードに到達できるか
  // 逆方向はグラフ自体逆で構成することで可能
  vector<bool> can_reach_from(int start) {
    vector<bool> reached(n + 1, false);
    dfs_reach_from(start, reached);
    return reached;
  }
  void dfs_reach_from(int now, vector<bool> &reached) {
    if (reached[now])
      return;
    reached[now] = true;
    for (auto e : g[now]) {
      dfs_reach_from(e.to, reached);
    }
  }

  // 出力
  void print() {
    for (auto v : g) {
      for (auto e : v) {
        std::cout << e.from << "-(" << e.weight << ")->" << e.to << ", ";
      }
      std::cout << std::endl;
    }
  }
};

//////////////////////////////////////

int main() {

  int N, M;
  cin >> N >> M;
  Graph<ll, ll> g(N);
  FOR(i, 1, N) { g.add_edge(i + 1, i, 0); }
  REP(i, M) {
    int l, r;
    ll c;
    cin >> l >> r;
    cin >> c;
    g.add_edge(l, r, c);
  }
  auto res = g.dijkstra(1);
  auto ans = res.first[N];
  if (ans == std::numeric_limits<ll>::max()) {
    cout << -1 << endl;
  } else {
    cout << ans << endl;
  }

  return 0;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cmath>
#include <fstream>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <unordered_set>
#include <vector>

#define MOD_BIG 1000000007
#define MOD_BIG2 998244353
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::string;
using ll = long long;
using pint = std::pair<int, int>;
using pll = std::pair<ll, ll>;
using std::vector;

#define FOR(i, begin, end)                                                     \
  for (int i = (begin), i##_end_ = (end); i < i##_end_; i++)
#define IFOR(i, begin, end)                                                    \
  for (int i = (end)-1, i##_begin_ = (begin); i >= i##_begin_; i--)
#define REP(i, n) FOR(i, 0, n)
#define IREP(i, n) IFOR(i, 0, n)

//////////////////////////////////////

enum Status {
  Not = 0,
  Now,
  End,
};

template <typename T> struct Edge {
  int to;
  int from;
  T weight;
  Edge(int from, int to, T weight) : from(from), to(to), weight(weight) {}
};

template <typename T, typename D> struct Graph {
  int n;
  vector<vector<Edge<T>>> g;
  vector<D> data;
  vector<Status> s;

  Graph(int N) : n(N), g(N + 1), data(N + 1), s(N + 1) {}

  void add_edge(int from, Edge<T> e) { g[from].push_back(e); }
  void add_edge(int from, int to, T weight) {
    g[from].push_back(Edge<T>(from, to, weight));
  }
  void set_data(int node, D value) { data[node] = value; }

  // 幅優先探索による最短経路
  // weightが全て同一の場合線形
  std::pair<vector<T>, vector<vector<Edge<T>>>> bfs_spp(int start) {
    vector<T> d(n + 1, -1);
    vector<vector<Edge<T>>> route(n + 1);
    std::queue<int> q;
    d[start] = 0;
    q.push(start);
    while (!q.empty()) {
      int v = q.front();
      q.pop();

      for (auto e : g[v]) {
        if (d[e.to] != -1 && d[e.to] != 0) {
          // 到達済み
          continue;
        }
        d[e.to] = d[e.from] + 1;
        auto tmp = route[e.from];
        tmp.push_back(e);
        route[e.to] = tmp;
        q.push(e.to);
      }
    }
    return std::make_pair(d, route);
  }

  // ダイクストラ法
  // weightが非負の場合の最短経路
  // 経路が存在しない場合、INFが返るのでオーバーフローに注意
  std::pair<vector<T>, vector<vector<Edge<T>>>> dijkstra(int start) {
    using P = std::pair<T, int>;
    std::priority_queue<P, vector<P>, std::greater<P>> que;
    T T_MAX = std::numeric_limits<T>::max();
    vector<T> d(n + 1, T_MAX);
    vector<vector<Edge<T>>> route(n + 1);
    d[start] = 0;
    que.push(P((T)0, start));
    while (!que.empty()) {
      P p = que.top();
      que.pop();
      int v = p.second;
      if (d[v] < p.first)
        continue;
      for (Edge<T> e : g[v]) {
        if (d[e.to] > d[v] + e.weight) {
          d[e.to] = d[v] + e.weight;
          que.push(P(d[e.to], e.to));
        }
      }
    }
    return std::make_pair(d, route);
  }

  // ベルマン-フォード法
  // weightを負を含む距離として最短経路を求める
  // 無限ループが存在する場合、trueを1つ目に返す
  std::pair<bool, vector<T>> bellman_ford(int start) {
    T T_INF = std::numeric_limits<T>::max();
    vector<T> d(n + 1, T_INF);
    vector<Edge<T>> E;
    for (int i = 0; i <= n; i++) {
      for (auto e : g[i]) {
        E.push_back(e);
      }
    }
    d[start] = 0;
    for (int i = 0; i <= n; i++) {
      for (auto e : E) {
        if (d[e.from] != T_INF && d[e.from] + e.weight < d[e.to]) {
          // 最初or別のstartからe.toへの最短路を発見
          d[e.to] = d[e.from] + e.weight;
          // std::cout << "new route find, to: " << e.to << ", distance: " <<
          // d[e.to] << std::endl;
          if (i == n) {
            // もう全ての辺はチェック済みのはずなのにまだ更新がある：無限ループあり
            return std::make_pair(true, d);
          }
        }
      }
    }
    return std::make_pair(false, d);
  }

  // あるノードに到達できるか
  // 逆方向はグラフ自体逆で構成することで可能
  vector<bool> can_reach_from(int start) {
    vector<bool> reached(n + 1, false);
    dfs_reach_from(start, reached);
    return reached;
  }
  void dfs_reach_from(int now, vector<bool> &reached) {
    if (reached[now])
      return;
    reached[now] = true;
    for (auto e : g[now]) {
      dfs_reach_from(e.to, reached);
    }
  }

  // 出力
  void print() {
    for (auto v : g) {
      for (auto e : v) {
        std::cout << e.from << "-(" << e.weight << ")->" << e.to << ", ";
      }
      std::cout << std::endl;
    }
  }
};

//////////////////////////////////////

int main() {

  int N, M;
  cin >> N >> M;
  Graph<ll, ll> g(N);
  FOR(i, 1, N) { g.add_edge(i + 1, i, 0); }
  REP(i, M) {
    int l, r;
    ll c;
    cin >> l >> r;
    cin >> c;
    g.add_edge(l, r, c);
  }
  auto res = g.dijkstra(1);
  auto ans = res.first[N];
  if (ans == std::numeric_limits<ll>::max()) {
    cout << -1 << endl;
  } else {
    cout << ans << endl;
  }

  return 0;
}