Problem p02925 (C++)

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

// varibable settings
#define infile "../test/sample-1.in"
#define int long long //{{{
const int INF = 1e18;
const int MOD = 1e9 + 7; //}}}

// define basic macro {{{
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)
#define _rrep(i, n) rrepi(i, 0, n)
#define rrepi(i, a, b) for (int i = (int)((b)-1); i >= (int)(a); --i)
#define rrep(...) _overload3(__VA_ARGS__, rrepi, _rrep, )(__VA_ARGS__)
#define each(i, a) for (auto &&i : a)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define uni(x)                                                                 \
  sort(all(x));                                                                \
  x.erase(unique(all(x)), x.end())
#define ub upper_bound
#define lb lower_bound
#define posl(A, x) (lower_bound(all(A), x) - A.begin())
#define posu(A, x) (upper_bound(all(A), x) - A.begin())
template <class T> inline void chmax(T &a, const T &b) {
  if ((a) < (b))
    (a) = (b);
}
template <class T> inline void chmin(T &a, const T &b) {
  if ((a) > (b))
    (a) = (b);
}

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long double ld;
typedef pair<int, int> pii;
typedef tuple<int, int, int> iii;

template <typename T> using PQ = priority_queue<T, vector<T>, greater<T>>;
struct Fast {
  Fast() {
    std::cin.tie(0);
    ios::sync_with_stdio(false);
  }
} fast;

#if defined(PCM) || defined(LOCAL)
#include "lib/dump.hpp"
#else
#define dump(...) 42
#define dump_1d(...) 42
#define dump_2d(...) 42
#endif
//}}}

struct pair_hash {
  template <class T1, class T2>
  std::size_t operator()(const std::pair<T1, T2> &p) const {
    auto h1 = std::hash<T1>{}(p.first);
    auto h2 = std::hash<T2>{}(p.second);

    // Mainly for demonstration purposes, i.e. works but is overly simple
    // In the real world, use sth. like boost.hash_combine
    return h1 ^ h2;
  }
};

int solve() {
  int n;
  cin >> n;
  int m = n * (n - 1) / 2;

  vvi M(n);
  rep(i, n) {
    rep(j, n - 1) {
      int a;
      cin >> a;
      a--;
      M[i].pb(a);
    }
  }
  dump_2d(M, n, n - 1);

  vector<pii> nodes;
  rep(i, n) rep(j, i + 1, n) { nodes.pb(mp(i, j)); }

  unordered_map<pii, vector<pii>, pair_hash> g;
  vvi h(n, vi(n));
  rep(i, n) {
    rep(j, 1, n - 1) {
      int pre = M[i][j - 1];
      int to = M[i][j];
      g[mp(min(i, pre), max(i, pre))].pb(mp(min(i, to), max(i, to)));
      h[i][to]++;
      h[to][i]++;
    }
  }
  dump(g);

  // 入次数が0の頂点の集合
  stack<pii> st;

  // 入次数が0の頂点であればstに追加
  each(i, nodes) if (h[i.first][i.second] == 0) st.push(i);

  // ソートされた後のグラフ
  set<pii> finish;

  // stがなくなるまでループ
  int cnt = 0;
  while (sz(finish) < m) {
    stack<pii> nex;
    while (st.size()) {
      // stの集合のから一つ取り出す
      pii i = st.top();
      st.pop();
      finish.insert(i);

      rep(k, sz(g[i])) {
        // 隣接する頂点の入次数をマイナス1
        auto j = g[i][k];
        h[j.first][j.second]--;
        h[j.second][j.first]--;
        if (h[j.first][j.second] == 0)
          nex.push(j);
      }
    }

    cnt++;
    dump(cnt, finish);

    // これによって入次数が0になればstに追加
    st = (nex);
    if (sz(st) == 0)
      break;
  }

  // ansを順に出力
  dump(finish);
  if (sz(finish) == m) {
    cout << cnt << endl;
  } else {
    cout << -1 << endl;
  }
  return 0;
}

signed main() { //{{{
#ifdef INPUT_FROM_FILE
  std::ifstream in(infile);
  std::cin.rdbuf(in.rdbuf());
#endif
  solve();
  return 0;
} //}}}


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

// varibable settings
#define infile "../test/sample-1.in"
#define int long long //{{{
const int INF = 1e18;
const int MOD = 1e9 + 7; //}}}

// define basic macro {{{
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)
#define _rrep(i, n) rrepi(i, 0, n)
#define rrepi(i, a, b) for (int i = (int)((b)-1); i >= (int)(a); --i)
#define rrep(...) _overload3(__VA_ARGS__, rrepi, _rrep, )(__VA_ARGS__)
#define each(i, a) for (auto &&i : a)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define uni(x)                                                                 \
  sort(all(x));                                                                \
  x.erase(unique(all(x)), x.end())
#define ub upper_bound
#define lb lower_bound
#define posl(A, x) (lower_bound(all(A), x) - A.begin())
#define posu(A, x) (upper_bound(all(A), x) - A.begin())
template <class T> inline void chmax(T &a, const T &b) {
  if ((a) < (b))
    (a) = (b);
}
template <class T> inline void chmin(T &a, const T &b) {
  if ((a) > (b))
    (a) = (b);
}

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long double ld;
typedef pair<int, int> pii;
typedef tuple<int, int, int> iii;

template <typename T> using PQ = priority_queue<T, vector<T>, greater<T>>;
struct Fast {
  Fast() {
    std::cin.tie(0);
    ios::sync_with_stdio(false);
  }
} fast;

#if defined(PCM) || defined(LOCAL)
#include "lib/dump.hpp"
#else
#define dump(...) 42
#define dump_1d(...) 42
#define dump_2d(...) 42
#endif
//}}}

struct pair_hash {
  template <class T1, class T2>
  std::size_t operator()(const std::pair<T1, T2> &p) const {
    auto h1 = std::hash<T1>{}(p.first);
    auto h2 = std::hash<T2>{}(p.second);

    // Mainly for demonstration purposes, i.e. works but is overly simple
    // In the real world, use sth. like boost.hash_combine
    return h1 ^ h2;
  }
};

int solve() {
  int n;
  cin >> n;
  int m = n * (n - 1) / 2;

  vvi M(n);
  rep(i, n) {
    rep(j, n - 1) {
      int a;
      cin >> a;
      a--;
      M[i].pb(a);
    }
  }
  dump_2d(M, n, n - 1);

  vector<pii> nodes;
  rep(i, n) rep(j, i + 1, n) { nodes.pb(mp(i, j)); }

  map<pii, vector<pii>> g;
  vvi h(n, vi(n));
  rep(i, n) {
    rep(j, 1, n - 1) {
      int pre = M[i][j - 1];
      int to = M[i][j];
      g[mp(min(i, pre), max(i, pre))].pb(mp(min(i, to), max(i, to)));
      h[i][to]++;
      h[to][i]++;
    }
  }
  dump(g);

  // 入次数が0の頂点の集合
  stack<pii> st;

  // 入次数が0の頂点であればstに追加
  each(i, nodes) if (h[i.first][i.second] == 0) st.push(i);

  // ソートされた後のグラフ
  set<pii> finish;

  // stがなくなるまでループ
  int cnt = 0;
  while (sz(finish) < m) {
    stack<pii> nex;
    while (st.size()) {
      // stの集合のから一つ取り出す
      pii i = st.top();
      st.pop();
      finish.insert(i);

      rep(k, sz(g[i])) {
        // 隣接する頂点の入次数をマイナス1
        auto j = g[i][k];
        h[j.first][j.second]--;
        h[j.second][j.first]--;
        if (h[j.first][j.second] == 0)
          nex.push(j);
      }
    }

    cnt++;
    dump(cnt, finish);

    // これによって入次数が0になればstに追加
    st = (nex);
    if (sz(st) == 0)
      break;
  }

  // ansを順に出力
  dump(finish);
  if (sz(finish) == m) {
    cout << cnt << endl;
  } else {
    cout << -1 << endl;
  }
  return 0;
}

signed main() { //{{{
#ifdef INPUT_FROM_FILE
  std::ifstream in(infile);
  std::cin.rdbuf(in.rdbuf());
#endif
  solve();
  return 0;
} //}}}