Problem p00967 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define dbg(...)                                                               \\
  do {                                                                         \\
    cerr << __LINE__ << ": ";                                                  \\
    dbgprint(#__VA_ARGS__, __VA_ARGS__);                                       \\
  } while (0);

using namespace std;

namespace std {
template <class S, class T> struct hash<pair<S, T>> {
  size_t operator()(const pair<S, T> &p) const {
    return ((size_t)1e9 + 7) * hash<S>()(p.first) + hash<T>()(p.second);
  }
};
template <class T> struct hash<vector<T>> {
  size_t operator()(const vector<T> &v) const {
    size_t h = 0;
    for (auto i : v)
      h = h * ((size_t)1e9 + 7) + hash<T>()(i) + 1;
    return h;
  }
};
} // namespace std
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[ ";
  rep(i, v.size()) os << v[i] << (i == v.size() - 1 ? " ]" : ", ");
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &v) {
  os << "{ ";
  for (const auto &i : v)
    os << i << ", ";
  return os << "}";
}
template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &v) {
  os << "{";
  for (const auto &i : v)
    os << " " << i.first << ": " << i.second << ",";
  return os << "}";
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << "(" << p.first << ", " << p.second << ")";
}
void dbgprint(const string &fmt) { cerr << endl; }
template <class H, class... T>
void dbgprint(const string &fmt, const H &h, const T &...r) {
  cerr << fmt.substr(0, fmt.find(",")) << "= " << h << " ";
  dbgprint(fmt.substr(fmt.find(",") + 1), r...);
}
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pi;
const int inf = (int)1e9;
const double INF = 1e12, EPS = 1e-9;

void bridge(const vector<vi> &g, vector<pi> &hasi) {
  int n = g.size(), cnt = 0;
  vi num(n, -1), low(n, inf);
  /*
  function<void(int,int)> rec = [&](int c, int p){
          num[c] = low[c] = cnt++;
          for(int i : g[c]) if(p != i){
                  if(num[i] >= 0) low[c] = min(low[c], num[i]);
                  else{
                          rec(i, c);
                          low[c] = min(low[c], low[i]);
                          if(low[i] > num[c]) hasi.emplace_back(c, i);
                  }
          }
  };
  rec(0, 0);
  */
  // stackに書き換え。やりたくねーーーー

  stack<tuple<int, int, int>> stk;
  stk.emplace(0, 0, -1);
  while (stk.size()) {
    int c, p, i;
  LABEL1:
    tie(c, p, i) = stk.top();
    stk.pop();
    if (i >= 0)
      goto LABEL2;

    num[c] = low[c] = cnt++;
    for (i = 0; i < g[c].size(); i++)
      if (p != g[c][i]) {
        if (num[g[c][i]] >= 0)
          low[c] = min(low[c], num[g[c][i]]);
        else {
          stk.emplace(c, p, i);
          stk.emplace(g[c][i], c, -1);
          goto LABEL1;
        LABEL2:

          low[c] = min(low[c], low[g[c][i]]);
          if (low[g[c][i]] > num[c])
            hasi.emplace_back(c, g[c][i]);
        }
      }
  }
}

vector<vector<pi>> in(vector<pi> &es) {
  int n, m;
  cin >> n >> m;
  vi p(n, -1);

  function<int(int)> root = [&](int x) {
    if (p[x] < 0)
      return x;
    return p[x] = root(p[x]);
  };
  auto merge = [&](int a, int b) {
    a = root(a);
    b = root(b);
    if (a == b)
      return 0;
    p[b] = a;
    return 1;
  };
  vector<vi> e(n + 1);
  vector<bool> mark(n + 1);
  rep(i, m) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    int loop_edge = !merge(a, b);
    if (loop_edge) {
      es.emplace_back(a, b);
      mark[a] = mark[b] = 1;
    } else {
      e[a].pb(b);
      e[b].pb(a);
    }
  }
  // まず橋は全部消してよい
  {
    vector<vi> e2 = e;
    vector<pi> hasi;
    for (pi p : es) {
      e2[p.first].pb(p.second);
      e2[p.second].pb(p.first);
    }
    bridge(e2, hasi);
    set<pi> hasis;
    for (auto p : hasi) {
      hasis.insert(p);
      hasis.emplace(p.second, p.first);
    }
    // dbg(hasis.size());
    rep(i, n) {
      vi ee;
      for (int j : e[i])
        if (!hasis.count(pi(i, j)))
          ee.pb(j);
      e[i] = ee;
    }
  }

  rep(i, n) if (e[i].size() > 2) mark[i] = 1;

  // 縮約
  // ここもgotoで再帰書き直しかよ！！ふざけんな！！！
  vector<bool> vis(n);
  rep(i, n) if (!vis[n] && mark[i]) {
    vi v;
    stack<tuple<int, int, int, int>> stk;
    stk.emplace(i, i, 0, -1);
    while (stk.size()) {
      int c, p, cnt, i;
    LABEL1:
      tie(c, p, cnt, i) = stk.top();
      stk.pop();
      if (i >= 0)
        goto LABEL2;

      if (!mark[c])
        cnt++;
      else
        cnt = 0;

      v.pb(c);
      vis[c] = 1;
      for (i = 0; i < e[c].size(); i++)
        if (e[c][i] != p) {

          if (mark[e[c][i]] && cnt > 1) {
            // dbg(v.size());

            int x = v[v.size() - cnt];
            for (vi::iterator j = e[x].begin(); j != e[x].end(); ++j)
              if (*j == v[v.size() - cnt + 1]) {
                e[x].erase(j);
                break;
              }
            for (vi::iterator j = e[e[c][i]].begin(); j != e[e[c][i]].end();
                 ++j)
              if (*j == c) {
                e[e[c][i]].erase(j);
                break;
              }
            e[x].pb(e[c][i]);
            e[e[c][i]].pb(x);
          }
          if (!vis[e[c][i]]) {
            stk.emplace(c, p, cnt, i);
            stk.emplace(e[c][i], c, cnt, -1);
            goto LABEL1;
          LABEL2:;
          }
          if (!mark[c])
            break;
        }
      v.pop_back();
    }
  }

  // rep(i, n) dbg(i, e[i]);

  // n番の頂点からたどれる頂点だけ取り出して番号を圧縮
  int N = 0;
  vi to(n, -1);
  function<void(int)> dfs = [&](int c) {
    to[c] = N++;
    for (auto i : e[c])
      if (to[i] < 0)
        dfs(i);
  };
  rep(i, n) if (to[i] < 0 && mark[i]) dfs(i);

  vector<vector<pi>> g(N);
  vector<pi> es2;
  rep(i, n) if (to[i] >= 0) for (int j : e[i]) if (to[j] >= 0) {
    g[to[i]].emplace_back(to[j], 0);
  }
  for (const auto &i : es) {
    assert(to[i.first] >= 0 && to[i.second] >= 0);
    // while(!(to[i.first] >= 0 && to[i.second] >= 0));
    // i = pi(to[i.first], to[i.second]);
    es2.emplace_back(to[i.first], to[i.second]);
  }
  es = es2;
  // dbg(N);dbg(es);

  return g;
}

void run() {
  cin.tie(0);
  cin.sync_with_stdio(0);
  vector<pi> es;
  vector<vector<pi>> g = in(es);

  // ループ列挙
  vector<bool> vis(g.size());
  vector<pi *> stk;
  function<int(int, int, int, int)> find_loop = [&](int c, int s, int t,
                                                    int id) {
    vis[c] = 1;
    if (c == t) {
      for (int i = (int)stk.size() - 1; i >= 0; i--)
        stk[i]->second |= 1 << id;
      return 1;
    }
    for (auto &i : g[c]) {
      if (vis[i.first])
        continue;
      stk.pb(&i);
      if (find_loop(i.first, s, t, id))
        return 1;
      stk.pop_back();
    }
    return 0;
  };
  int m = es.size();
  rep(i, m) {
    fill(all(vis), 0);
    stk.clear();
    int a = es[i].first, b = es[i].second;
    int res = find_loop(a, a, b, i);
    while (!res)
      ;
  }
  rep(i, m) {
    int a = es[i].first, b = es[i].second;
    g[a].emplace_back(b, 1 << i);
    g[b].emplace_back(a, 1 << i);
  }
  // rep(i, g.size()) dbg(i, g[i]);

  // 逆辺にフラグ立てるの忘れてた
  map<pi, pi *> tbl;
  rep(i, g.size()) for (auto &j : g[i]) tbl[pi(i, j.first)] = &j;
  rep(i, g.size()) for (auto &j : g[i]) {
    int b = j.second | tbl[pi(j.first, i)]->second;
    // dbg(i, j.first, b, j.second, *tbl[pi(j.first, i)]);
    j.second = tbl[pi(j.first, i)]->second = b;
  }
  // rep(i, g.size()) dbg(i, g[i]);

  // 数える
  // dfsして連結かつループで誘導されるグラフの頂点が全て次数が2
  function<int(int, int)> dfs = [&](int c, int bit) {
    vis[c] = 1;
    int deg = 0, res = 1;
    for (auto i : g[c]) {
      if (__builtin_popcount(i.second & bit) % 2 == 0)
        continue;
      if (!vis[i.first])
        res &= dfs(i.first, bit);
      deg++;
    }
    if (deg != 2)
      return 0;
    return res;
  };
  int ans = 0;
  rep(i, 1 << m) {
    fill(all(vis), 0);
    int v = -1;
    rep(j,
        g.size()) for (pi k : g[j]) if (__builtin_popcount(k.second & i) % 2) {
      v = j;
      break;
    }
    // dbg(v);

    if (v < 0 || !dfs(v, i))
      continue;
    rep(j, g.size()) {
      bool f = 0;
      for (pi k : g[j])
        if (__builtin_popcount(k.second & i) % 2) {
          f = 1;
          break;
        }
      if (f != vis[j])
        goto FAIL;
    }
    ans++;
  FAIL:;
  }
  cout << ans << endl;
}

int main() {
  run();
  return 0;
}


Error: 0

Fixed submission:

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define dbg(...)                                                               \\
  do {                                                                         \\
    cerr << __LINE__ << ": ";                                                  \\
    dbgprint(#__VA_ARGS__, __VA_ARGS__);                                       \\
  } while (0);

using namespace std;

namespace std {
template <class S, class T> struct hash<pair<S, T>> {
  size_t operator()(const pair<S, T> &p) const {
    return ((size_t)1e9 + 7) * hash<S>()(p.first) + hash<T>()(p.second);
  }
};
template <class T> struct hash<vector<T>> {
  size_t operator()(const vector<T> &v) const {
    size_t h = 0;
    for (auto i : v)
      h = h * ((size_t)1e9 + 7) + hash<T>()(i) + 1;
    return h;
  }
};
} // namespace std
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[ ";
  rep(i, v.size()) os << v[i] << (i == v.size() - 1 ? " ]" : ", ");
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &v) {
  os << "{ ";
  for (const auto &i : v)
    os << i << ", ";
  return os << "}";
}
template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &v) {
  os << "{";
  for (const auto &i : v)
    os << " " << i.first << ": " << i.second << ",";
  return os << "}";
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << "(" << p.first << ", " << p.second << ")";
}
void dbgprint(const string &fmt) { cerr << endl; }
template <class H, class... T>
void dbgprint(const string &fmt, const H &h, const T &...r) {
  cerr << fmt.substr(0, fmt.find(",")) << "= " << h << " ";
  dbgprint(fmt.substr(fmt.find(",") + 1), r...);
}
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pi;
const int inf = (int)1e9;
const double INF = 1e12, EPS = 1e-9;

void bridge(const vector<vi> &g, vector<pi> &hasi) {
  int n = g.size(), cnt = 0;
  vi num(n, -1), low(n, inf);
  /*
  function<void(int,int)> rec = [&](int c, int p){
          num[c] = low[c] = cnt++;
          for(int i : g[c]) if(p != i){
                  if(num[i] >= 0) low[c] = min(low[c], num[i]);
                  else{
                          rec(i, c);
                          low[c] = min(low[c], low[i]);
                          if(low[i] > num[c]) hasi.emplace_back(c, i);
                  }
          }
  };
  rec(0, 0);
  */
  // stackに書き換え。やりたくねーーーー

  stack<tuple<int, int, int>> stk;
  stk.emplace(0, 0, -1);
  while (stk.size()) {
    int c, p, i;
  LABEL1:
    tie(c, p, i) = stk.top();
    stk.pop();
    if (i >= 0)
      goto LABEL2;

    num[c] = low[c] = cnt++;
    for (i = 0; i < g[c].size(); i++)
      if (p != g[c][i]) {
        if (num[g[c][i]] >= 0)
          low[c] = min(low[c], num[g[c][i]]);
        else {
          stk.emplace(c, p, i);
          stk.emplace(g[c][i], c, -1);
          goto LABEL1;
        LABEL2:

          low[c] = min(low[c], low[g[c][i]]);
          if (low[g[c][i]] > num[c])
            hasi.emplace_back(c, g[c][i]);
        }
      }
  }
}

vector<vector<pi>> in(vector<pi> &es) {
  int n, m;
  cin >> n >> m;
  vi p(n, -1);

  function<int(int)> root = [&](int x) {
    if (p[x] < 0)
      return x;
    return p[x] = root(p[x]);
  };
  auto merge = [&](int a, int b) {
    a = root(a);
    b = root(b);
    if (a == b)
      return 0;
    p[b] = a;
    return 1;
  };
  vector<vi> e(n + 1);
  vector<bool> mark(n + 1);
  rep(i, m) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    int loop_edge = !merge(a, b);
    if (loop_edge) {
      es.emplace_back(a, b);
      mark[a] = mark[b] = 1;
    } else {
      e[a].pb(b);
      e[b].pb(a);
    }
  }
  // まず橋は全部消してよい
  {
    vector<vi> e2 = e;
    vector<pi> hasi;
    for (pi p : es) {
      e2[p.first].pb(p.second);
      e2[p.second].pb(p.first);
    }
    bridge(e2, hasi);
    set<pi> hasis;
    for (auto p : hasi) {
      hasis.insert(p);
      hasis.emplace(p.second, p.first);
    }
    // dbg(hasis.size());
    rep(i, n) {
      vi ee;
      for (int j : e[i])
        if (!hasis.count(pi(i, j)))
          ee.pb(j);
      e[i] = ee;
    }
  }

  int mk = 0, mkc = 0;
  rep(i, n) if (e[i].size() > 2) mark[mk = i] = 1, mkc++;
  assert(es.size() == m - n + 1);
  // while(!(es.size() == m - n + 1));
  // dbg(mk, mkc);
  e[n].pb(mk);
  e[mk].pb(n);
  n++;

  // 縮約
  // ここもgotoで再帰書き直しかよ！！ふざけんな！！！
  vector<bool> vis(n);
  vi v;
  stack<tuple<int, int, int, int>> stk;
  stk.emplace(n - 1, n - 1, 0, -1);
  while (stk.size()) {
    int c, p, cnt, i;
  LABEL1:
    tie(c, p, cnt, i) = stk.top();
    stk.pop();
    if (i >= 0)
      goto LABEL2;

    if (!mark[c])
      cnt++;
    else
      cnt = 0;

    v.pb(c);
    vis[c] = 1;
    for (i = 0; i < e[c].size(); i++)
      if (e[c][i] != p) {

        if (mark[e[c][i]] && cnt > 1) {
          // dbg(v.size());

          int x = v[v.size() - cnt];
          for (vi::iterator j = e[x].begin(); j != e[x].end(); ++j)
            if (*j == v[v.size() - cnt + 1]) {
              e[x].erase(j);
              break;
            }
          for (vi::iterator j = e[e[c][i]].begin(); j != e[e[c][i]].end(); ++j)
            if (*j == c) {
              e[e[c][i]].erase(j);
              break;
            }
          e[x].pb(e[c][i]);
          e[e[c][i]].pb(x);
        }
        if (!vis[e[c][i]]) {
          stk.emplace(c, p, cnt, i);
          stk.emplace(e[c][i], c, cnt, -1);
          goto LABEL1;
        LABEL2:;
        }
        if (!mark[c])
          break;
      }
    v.pop_back();
  }

  // rep(i, n) dbg(i, e[i]);

  // n番の頂点からたどれる頂点だけ取り出して番号を圧縮
  int N = 0;
  vi to(n, -1);
  function<void(int)> dfs = [&](int c) {
    to[c] = N++;
    for (auto i : e[c])
      if (to[i] < 0)
        dfs(i);
  };
  dfs(n - 1);

  vector<vector<pi>> g(N);
  vector<pi> es2;
  rep(i, n) if (to[i] >= 0) for (int j : e[i]) if (to[j] >= 0) {
    g[to[i]].emplace_back(to[j], 0);
  }
  for (const auto &i : es) {
    assert(to[i.first] >= 0 && to[i.second] >= 0);
    // while(!(to[i.first] >= 0 && to[i.second] >= 0));
    // i = pi(to[i.first], to[i.second]);
    es2.emplace_back(to[i.first], to[i.second]);
  }
  es = es2;
  // dbg(N);dbg(es);

  return g;
}

void run() {
  cin.tie(0);
  cin.sync_with_stdio(0);
  vector<pi> es;
  vector<vector<pi>> g = in(es);

  // ループ列挙
  vector<bool> vis(g.size());
  vector<pi *> stk;
  function<int(int, int, int, int)> find_loop = [&](int c, int s, int t,
                                                    int id) {
    vis[c] = 1;
    if (c == t) {
      for (int i = (int)stk.size() - 1; i >= 0; i--)
        stk[i]->second |= 1 << id;
      return 1;
    }
    for (auto &i : g[c]) {
      if (vis[i.first])
        continue;
      stk.pb(&i);
      if (find_loop(i.first, s, t, id))
        return 1;
      stk.pop_back();
    }
    return 0;
  };
  int m = es.size();
  rep(i, m) {
    fill(all(vis), 0);
    stk.clear();
    int a = es[i].first, b = es[i].second;
    int res = find_loop(a, a, b, i);
    while (!res)
      ;
  }
  rep(i, m) {
    int a = es[i].first, b = es[i].second;
    g[a].emplace_back(b, 1 << i);
    g[b].emplace_back(a, 1 << i);
  }
  // rep(i, g.size()) dbg(i, g[i]);

  // 逆辺にフラグ立てるの忘れてた
  map<pi, pi *> tbl;
  rep(i, g.size()) for (auto &j : g[i]) tbl[pi(i, j.first)] = &j;
  rep(i, g.size()) for (auto &j : g[i]) {
    int b = j.second | tbl[pi(j.first, i)]->second;
    // dbg(i, j.first, b, j.second, *tbl[pi(j.first, i)]);
    j.second = tbl[pi(j.first, i)]->second = b;
  }
  // rep(i, g.size()) dbg(i, g[i]);

  // 数える
  // dfsして連結かつループで誘導されるグラフの頂点が全て次数が2
  function<int(int, int)> dfs = [&](int c, int bit) {
    vis[c] = 1;
    int deg = 0, res = 1;
    for (auto i : g[c]) {
      if (__builtin_popcount(i.second & bit) % 2 == 0)
        continue;
      if (!vis[i.first])
        res &= dfs(i.first, bit);
      deg++;
    }
    if (deg != 2)
      return 0;
    return res;
  };
  int ans = 0;
  rep(i, 1 << m) {
    fill(all(vis), 0);
    int v = -1;
    rep(j,
        g.size()) for (pi k : g[j]) if (__builtin_popcount(k.second & i) % 2) {
      v = j;
      break;
    }
    // dbg(v);

    if (v < 0 || !dfs(v, i))
      continue;
    rep(j, g.size()) {
      bool f = 0;
      for (pi k : g[j])
        if (__builtin_popcount(k.second & i) % 2) {
          f = 1;
          break;
        }
      if (f != vis[j])
        goto FAIL;
    }
    ans++;
  FAIL:;
  }
  cout << ans << endl;
}

int main() {
  run();
  return 0;
}