Problem p02991 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;

#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define MIN(a) *min_element(all(a))
#define MAX(a) *max_element(all(a))
#define SUM(a) accumulate(all(a), 0LL)
#define REP(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define RREP(i, n) for (int(i) = (n)-1; (i) >= 0; (i)--)
#define FOR(i, m, n) for (int(i) = (m); (i) < (n); i++)
#define FORR(i, m, n) for (int(i) = (n)-1; (i) >= (m); i--)
#define debug(x) cerr << #x << " = " << x << endl
// #define int long long

typedef long long ll;
// ll const MOD = 998244353;
ll const MOD = 1e9 + 7;
int const inf = 1e9;
ll const INF = 1e18;

inline void ios_() {
  cin.tie(0);
  ios::sync_with_stdio(false);
}
template <typename T> int size(const T &a) { return (int)a.size(); }
template <typename T> T Div(T a, T b) { return (a + b - 1) / b; }
template <typename T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

// Graph in adjcency list
class Graph {
  struct edge {
    int from;
    int to;
    ll cost;
    edge(int a, ll b) : to(a), cost(b) {}
    edge(int a, int b, ll c) : from(a), to(b), cost(c) {}
  };

public:
  int N;                        // 頂点数
  vector<vector<edge>> adjlist; // 隣接リスト
  vector<ll> depth;             // ノードの深さ
  vector<bool> check;           // 訪問済みの頂点を記録
  ll diam;                      // 木の直径
  vector<int> deg;              // 入次数
  vector<int> tsort;            // トポロジカルソートの結果

  Graph(int n)
      : N(n), adjlist(n), depth(n, INF), check(n, false), diam(INF), deg(n, 0) {
  }

  void setEdge(int a, int b, ll c) { // 辺を追加
    adjlist[a].push_back(edge(b, c));
    deg[b]++;
  }

  void dfs(int p, int v, ll d) { // 深さ優先探索
    if (check[v])
      return;

    check[v] = true;
    depth[v] = d;

    for (auto i : adjlist[v]) {
      if (i.to == p)
        continue;
      dfs(v, i.to, d + i.cost);
    }
  }

  void bfs(int v) { // 幅優先探索
    queue<edge> que;
    for (auto i : adjlist[v])
      que.push(i);

    check[v] = true;

    while (!que.empty()) {
      int u = que.front().to;
      ll d = que.front().cost;
      que.pop();

      check[u] = true;
      depth[u] = d;

      for (auto i : adjlist[u]) {
        if (!check[i.to]) {
          que.push(edge(i.to, d + i.cost));
        }
      }
    }
  }

  ll diameter() { // 木の直径を求める
    if (diam != INF)
      return diam; // 計算済みの場合

    dfs(-1, 0, 0); // 頂点0からの最遠頂点vを求める
    int v = max_element(all(depth)) - depth.begin();

    REP(i, N) {
      check[i] = false;
      depth[i] = 0;
    }

    dfs(-1, v, 0); // vからの最遠頂点を求める

    return diam = MAX(depth); // この2頂点間の距離が直径
  }

  void dijkstra(int start) { // ダイクストラ法
    depth[start] = 0;

    auto fn = [](edge a, edge b) { return a.cost > b.cost; };
    priority_queue<edge, vector<edge>, decltype(fn)> que(fn);

    for (auto i : adjlist[start])
      que.push(i);

    while (!que.empty()) {
      auto v = que.top().to;
      auto d = que.top().cost;
      que.pop();

      if (depth[v] < INF)
        continue;
      else
        depth[v] = d;

      for (auto i : adjlist[v]) {
        if (depth[i.to] == INF) {
          que.push(edge(i.to, i.cost + d));
        }
      }
    }
  }

  bool BellmanFord(
      int start) { // ベルマンフォード法 (負の閉路がある場合はtrueを返す)
    depth[start] = 0;
    REP(i, N) {
      REP(j, N) {
        for (auto k : adjlist[j]) {
          if (check[j] && depth[j] + k.cost < depth[k.to]) {
            if (i == N - 1)
              return true; // N回目にも更新があるなら負の閉路が存在
            depth[k.to] = depth[j] + k.cost;
          }
        }
      }
    }
    return false;
  }

  void topologicalSort() { // トポロジカルソート
    deque<int> deq;
    REP(i, N) {
      if (deg[i] == 0)
        deq.push_back(i);
    }

    while (!deq.empty()) {
      auto v = deq.front();
      deq.pop_front();
      tsort.push_back(v);
      for (auto i : adjlist[v]) {
        deg[i.to]--;
        if (deg[i.to] == 0)
          deq.push_back(i.to);
      }
    }
  }
};

signed main() {
  ios_();
  int n, m;
  cin >> n >> m;

  Graph G(3 * n);
  REP(i, m) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    REP(j, 3) { G.setEdge(3 * a + j, 3 * b + (j + 1) % 3, 1); }
  }

  int start, goal;
  cin >> start >> goal;
  start--;
  goal--;

  G.bfs(start * 3);
  ll ans = G.depth[3 * goal];
  cout << (ans < INF ? ans / 3 : -1) << endl;

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;

#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define MIN(a) *min_element(all(a))
#define MAX(a) *max_element(all(a))
#define SUM(a) accumulate(all(a), 0LL)
#define REP(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define RREP(i, n) for (int(i) = (n)-1; (i) >= 0; (i)--)
#define FOR(i, m, n) for (int(i) = (m); (i) < (n); i++)
#define FORR(i, m, n) for (int(i) = (n)-1; (i) >= (m); i--)
#define debug(x) cerr << #x << " = " << x << endl
// #define int long long

typedef long long ll;
// ll const MOD = 998244353;
ll const MOD = 1e9 + 7;
int const inf = 1e9;
ll const INF = 1e18;

inline void ios_() {
  cin.tie(0);
  ios::sync_with_stdio(false);
}
template <typename T> int size(const T &a) { return (int)a.size(); }
template <typename T> T Div(T a, T b) { return (a + b - 1) / b; }
template <typename T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

// Graph in adjcency list
class Graph {
  struct edge {
    int from;
    int to;
    ll cost;
    edge(int a, ll b) : to(a), cost(b) {}
    edge(int a, int b, ll c) : from(a), to(b), cost(c) {}
  };

public:
  int N;                        // 頂点数
  vector<vector<edge>> adjlist; // 隣接リスト
  vector<ll> depth;             // ノードの深さ
  vector<bool> check;           // 訪問済みの頂点を記録
  ll diam;                      // 木の直径
  vector<int> deg;              // 入次数
  vector<int> tsort;            // トポロジカルソートの結果

  Graph(int n)
      : N(n), adjlist(n), depth(n, INF), check(n, false), diam(INF), deg(n, 0) {
  }

  void setEdge(int a, int b, ll c) { // 辺を追加
    adjlist[a].push_back(edge(b, c));
    deg[b]++;
  }

  void dfs(int p, int v, ll d) { // 深さ優先探索
    if (check[v])
      return;

    check[v] = true;
    depth[v] = d;

    for (auto i : adjlist[v]) {
      if (i.to == p)
        continue;
      dfs(v, i.to, d + i.cost);
    }
  }

  void bfs(int v) { // 幅優先探索
    queue<edge> que;
    for (auto i : adjlist[v])
      que.push(i);

    check[v] = true;

    while (!que.empty()) {
      int u = que.front().to;
      ll d = que.front().cost;
      que.pop();

      check[u] = true;
      depth[u] = d;

      for (auto i : adjlist[u]) {
        if (!check[i.to]) {
          que.push(edge(i.to, d + i.cost));
        }
      }
    }
  }

  ll diameter() { // 木の直径を求める
    if (diam != INF)
      return diam; // 計算済みの場合

    dfs(-1, 0, 0); // 頂点0からの最遠頂点vを求める
    int v = max_element(all(depth)) - depth.begin();

    REP(i, N) {
      check[i] = false;
      depth[i] = 0;
    }

    dfs(-1, v, 0); // vからの最遠頂点を求める

    return diam = MAX(depth); // この2頂点間の距離が直径
  }

  void dijkstra(int start) { // ダイクストラ法
    depth[start] = 0;

    auto fn = [](edge a, edge b) { return a.cost > b.cost; };
    priority_queue<edge, vector<edge>, decltype(fn)> que(fn);

    for (auto i : adjlist[start])
      que.push(i);

    while (!que.empty()) {
      auto v = que.top().to;
      auto d = que.top().cost;
      que.pop();

      if (depth[v] < INF)
        continue;
      else
        depth[v] = d;

      for (auto i : adjlist[v]) {
        if (depth[i.to] == INF) {
          que.push(edge(i.to, i.cost + d));
        }
      }
    }
  }

  bool BellmanFord(
      int start) { // ベルマンフォード法 (負の閉路がある場合はtrueを返す)
    depth[start] = 0;
    REP(i, N) {
      REP(j, N) {
        for (auto k : adjlist[j]) {
          if (check[j] && depth[j] + k.cost < depth[k.to]) {
            if (i == N - 1)
              return true; // N回目にも更新があるなら負の閉路が存在
            depth[k.to] = depth[j] + k.cost;
          }
        }
      }
    }
    return false;
  }

  void topologicalSort() { // トポロジカルソート
    deque<int> deq;
    REP(i, N) {
      if (deg[i] == 0)
        deq.push_back(i);
    }

    while (!deq.empty()) {
      auto v = deq.front();
      deq.pop_front();
      tsort.push_back(v);
      for (auto i : adjlist[v]) {
        deg[i.to]--;
        if (deg[i.to] == 0)
          deq.push_back(i.to);
      }
    }
  }
};

signed main() {
  ios_();
  int n, m;
  cin >> n >> m;

  Graph G(3 * n);
  REP(i, m) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    REP(j, 3) { G.setEdge(3 * a + j, 3 * b + (j + 1) % 3, 1); }
  }

  int start, goal;
  cin >> start >> goal;
  start--;
  goal--;

  G.dijkstra(start * 3);
  ll ans = G.depth[3 * goal];
  cout << (ans < INF ? ans / 3 : -1) << endl;

  return 0;
}