Problem p02902 (C++)

Buggy submission (status: Time Limit Exceeded):
#define _USE_MATH_DEFINES

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

typedef pair<long long int, long long int> P;
typedef tuple<int, int, int> T;

long long int INF = 1e18;
long long int MOD = 1e9 + 7;

#define MAX_V 11000

int V;
vector<int> G[MAX_V];  // グラフの隣接リスト表現
vector<int> rG[MAX_V]; // 辺の向きを逆にしたグラフ
vector<int> vs;        // 帰りがけ順の並び
bool used[MAX_V];      // すでに調べたか
int cmp[MAX_V];        // 属する強連結成分のトポロジカル順序

// from から to への辺を張る関数
void add_edge(int from, int to) {
  G[from].push_back(to);
  rG[to].push_back(from);
}

void dfs(int v) {
  used[v] = true;
  for (int i = 0; i < G[v].size(); i++) {
    if (!used[G[v][i]]) {
      dfs(G[v][i]);
    }
  }
  vs.push_back(v);
}

void rdfs(int v, int k) {
  used[v] = true;
  cmp[v] = k;
  for (int i = 0; i < rG[v].size(); i++) {
    if (!used[rG[v][i]]) {
      rdfs(rG[v][i], k);
    }
  }
}

// 強連結成分分解を行う関数、返り値は強連結成分の個数
int scc() {
  memset(used, 0, sizeof(used));
  vs.clear();
  for (int v = 0; v < V; v++) {
    if (!used[v]) {
      dfs(v);
    }
  }
  memset(used, 0, sizeof(used));
  int k = 0;
  for (int i = vs.size() - 1; i >= 0; i--) {
    if (!used[vs[i]]) {
      rdfs(vs[i], k++);
    }
  }
  return k;
}

vector<int> vert[1100];
vector<int> ans;

bool inUse[MAX_V];

bool func(bool flag, int fst, int pos) {
  if (flag && fst == pos) {
    ans.push_back(pos);
    return true;
  }
  if (used[pos]) {
    return false;
  }
  used[pos] = true;
  for (int to : G[pos]) {
    if (inUse[to]) {
      bool ret = func(true, fst, to);
      if (ret) {
        ans.push_back(pos);
        return true;
      }
    }
  }
  return false;
}

int main() {
  int M;
  cin >> V >> M;
  for (int i = 0; i < M; i++) {
    int A, B;
    cin >> A >> B;
    add_edge(A - 1, B - 1);
  }
  int cnt = scc();
  if (cnt == V) {
    cout << -1 << endl;
    return 0;
  }
  for (int i = 0; i < V; i++) {
    vert[cmp[i]].push_back(i);
  }
  for (int loop = 0; loop < cnt; loop++) {
    if (vert[loop].size() >= 2) {
      while (true) {
        bool flag = true;
        memset(used, 0, sizeof(used));
        memset(inUse, 0, sizeof(inUse));
        for (int pos : vert[loop]) {
          inUse[pos] = true;
        }
        ans.clear();
        func(false, vert[loop][0], vert[loop][0]);
        reverse(ans.begin(), ans.end());
        /*
        for(int i = 0; i < ans.size(); i++){
                cout << ans[i] << " ";
        }cout << endl;
        */
        for (int i = 0; i < ans.size() - 1; i++) {
          int pos = ans[i];
          for (int to : G[pos]) {
            if (inUse[to] && to != ans[i + 1]) {
              flag = false;
              vert[loop].clear();
              vert[loop].push_back(pos);
              ans.pop_back();
              int sz = ans.size();
              int j = i;
              while (ans[j % sz] != to) {
                j += 1;
              }
              while (ans[j % sz] != pos) {
                vert[loop].push_back(ans[j % sz]);
                j += 1;
              }
              break;
            }
          }
          if (!flag) {
            break;
          }
        }
        if (flag) {
          break;
        }
      }
      break;
    }
  }
  ans.pop_back();
  cout << ans.size() << endl;
  for (int pos : ans) {
    cout << pos + 1 << endl;
  }
  return 0;
}

Fixed submission:
#define _USE_MATH_DEFINES

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

typedef pair<long long int, long long int> P;
typedef tuple<int, int, int> T;

long long int INF = 1e18;
long long int MOD = 1e9 + 7;

#define MAX_V 11000

int V;
vector<int> G[MAX_V];  // グラフの隣接リスト表現
vector<int> rG[MAX_V]; // 辺の向きを逆にしたグラフ
vector<int> vs;        // 帰りがけ順の並び
bool used[MAX_V];      // すでに調べたか
int cmp[MAX_V];        // 属する強連結成分のトポロジカル順序

// from から to への辺を張る関数
void add_edge(int from, int to) {
  G[from].push_back(to);
  rG[to].push_back(from);
}

void dfs(int v) {
  used[v] = true;
  for (int i = 0; i < G[v].size(); i++) {
    if (!used[G[v][i]]) {
      dfs(G[v][i]);
    }
  }
  vs.push_back(v);
}

void rdfs(int v, int k) {
  used[v] = true;
  cmp[v] = k;
  for (int i = 0; i < rG[v].size(); i++) {
    if (!used[rG[v][i]]) {
      rdfs(rG[v][i], k);
    }
  }
}

// 強連結成分分解を行う関数、返り値は強連結成分の個数
int scc() {
  memset(used, 0, sizeof(used));
  vs.clear();
  for (int v = 0; v < V; v++) {
    if (!used[v]) {
      dfs(v);
    }
  }
  memset(used, 0, sizeof(used));
  int k = 0;
  for (int i = vs.size() - 1; i >= 0; i--) {
    if (!used[vs[i]]) {
      rdfs(vs[i], k++);
    }
  }
  return k;
}

vector<int> vert[1100];
vector<int> ans;

bool inUse[MAX_V];

bool func(bool flag, int fst, int pos) {
  if (flag && fst == pos) {
    ans.push_back(pos);
    return true;
  }
  if (used[pos]) {
    return false;
  }
  used[pos] = true;
  for (int to : G[pos]) {
    if (inUse[to]) {
      bool ret = func(true, fst, to);
      if (ret) {
        ans.push_back(pos);
        return true;
      }
    }
  }
  return false;
}

int main() {
  int M;
  cin >> V >> M;
  for (int i = 0; i < M; i++) {
    int A, B;
    cin >> A >> B;
    add_edge(A - 1, B - 1);
  }
  int cnt = scc();
  if (cnt == V) {
    cout << -1 << endl;
    return 0;
  }
  for (int i = 0; i < V; i++) {
    vert[cmp[i]].push_back(i);
  }
  for (int loop = 0; loop < cnt; loop++) {
    if (vert[loop].size() >= 2) {
      while (true) {
        bool flag = true;
        memset(used, 0, sizeof(used));
        memset(inUse, 0, sizeof(inUse));
        for (int pos : vert[loop]) {
          inUse[pos] = true;
        }
        ans.clear();
        func(false, vert[loop][0], vert[loop][0]);
        reverse(ans.begin(), ans.end());
        memset(inUse, 0, sizeof(inUse));
        for (int pos : ans) {
          inUse[pos] = true;
        }
        /*
        for(int i = 0; i < ans.size(); i++){
                cout << ans[i] << " ";
        }cout << endl;
        */
        for (int i = 0; i < ans.size() - 1; i++) {
          int pos = ans[i];
          for (int to : G[pos]) {
            if (inUse[to] && to != ans[i + 1]) {
              flag = false;
              vert[loop].clear();
              vert[loop].push_back(pos);
              ans.pop_back();
              int sz = ans.size();
              int j = i;
              while (ans[j % sz] != to) {
                j += 1;
              }
              while (ans[j % sz] != pos) {
                vert[loop].push_back(ans[j % sz]);
                j += 1;
              }
              break;
            }
          }
          if (!flag) {
            break;
          }
        }
        if (flag) {
          break;
        }
      }
      break;
    }
  }
  ans.pop_back();
  cout << ans.size() << endl;
  for (int pos : ans) {
    cout << pos + 1 << endl;
  }
  return 0;
}