Problem p03201 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#include <stdio.h>

using namespace std;
typedef int ll;

const int N = 200005;

const int E = 2000006;
vector<int> g[N];

int ne;
struct Edge {
  int from, to;
  ll flow, cap;
} edge[E];

int lvl[N], vis[N], pass, start = N - 2, target = N - 1;
int qu[N], qt, px[N];

ll run(int s, int sink, ll minE) {
  if (s == sink)
    return minE;

  ll ans = 0;

  for (; px[s] < (int)g[s].size(); px[s]++) {
    int e = g[s][px[s]];
    auto &v = edge[e], &rev = edge[e ^ 1];
    if (lvl[v.to] != lvl[s] + 1 || v.flow >= v.cap)
      continue;
    ll tmp = run(v.to, sink, min(minE, v.cap - v.flow));
    v.flow += tmp, rev.flow -= tmp;
    ans += tmp, minE -= tmp;
    if (minE == 0)
      break;
  }
  return ans;
}

bool bfs(int source, int sink) {
  qt = 0;
  qu[qt++] = source;
  lvl[source] = 1;
  vis[source] = ++pass;

  for (int i = 0; i < qt; i++) {
    int u = qu[i];
    px[u] = 0;
    if (u == sink)
      return true;

    for (int e : g[u]) {
      auto v = edge[e];
      if (v.flow >= v.cap || vis[v.to] == pass)
        continue;
      vis[v.to] = pass;
      lvl[v.to] = lvl[u] + 1;
      qu[qt++] = v.to;
    }
  }
  return false;
}

ll flow(int source = start, int sink = target) {
  ll ans = 0;
  while (bfs(source, sink))
    ans += run(source, sink, N);
  return ans;
}

void addEdge(int u, int v, ll c = 1, ll rc = 0) {
  edge[ne] = {u, v, 0, c};
  g[u].push_back(ne++);
  edge[ne] = {v, u, 0, rc};
  g[v].push_back(ne++);
}

int c[N];
int er[N];
void dfs(int u) {

  for (int e : g[u]) {
    auto v = edge[e];
    if (er[v.to])
      continue;
    if (c[v.to] == c[u])
      assert(0);
    if (!c[v.to])
      c[v.to] = 3 - c[u], dfs(v.to);
  }
}

int n, v[N];

int deg[N];
// vector<pair<int, int>> edg;

map<int, vector<int>> cnt;
int build(int val) {
  int ans = 0;

  // cnt.clear();
  for (int i = 0; i < n; i++)
    if (!deg[i]) {
      if (cnt.count(val - v[i])) {
        int j;
        do {
          j = cnt[val - v[i]].back();
          cnt[val - v[i]].pop_back();
          if (i == j) {
            if (!cnt[val - v[i]].empty()) {
              j = cnt[val - v[i]].back();
              cnt[val - v[i]].back() = i;
            } else {
              cnt[val - v[i]].push_back(i);
              break;
            }
          }
        } while (deg[j]);
        if (i == j)
          continue;
        if (cnt[val - v[i]].empty())
          cnt.erase(val - v[i]);
        deg[i]++, deg[j]++;
        // edge.emplace_back(j, i);
        ans++;
        // addEdge(i, j, 1, 1);
      }
      // else cnt[ v[i] ].push_back(i);
    }
  return ans;
}

int clean() {
  int ans = 0;

  queue<int> q;

  for (int i = 0; i < n; i++)
    if (deg[i] == 1) {
      q.push(i);
    }

  int u;
  while (!q.empty()) {
    u = q.front();
    q.pop();
    if (er[u])
      continue;
    int e = g[u][0];
    g[u].clear();
    ans++;
    er[u] = er[edge[e].to] = 1;
    for (int e2 : g[edge[e].to]) {
      if (er[edge[e2].to])
        continue;
      deg[edge[e2].to]--;
      edge[e2 ^ 1].cap = 0;
      if (deg[edge[e2].to] == 1) {
        q.push(edge[e2].to);
      }
    }
    g[edge[e].to].clear();
  }

  return ans;
}

int main() {

  scanf("%d", &n);

  for (int i = 0; i < n; i++)
    scanf("%d", v + i);

  for (int i = 0; i < n; i++)
    cnt[v[i]].push_back(i);

  int ans = 0;
  for (int i = 30; i >= 0; i--)
    ans += build(1 << i);

  printf("%d\n", ans);
  return 0;

  // int ans = clean();

  for (int i = 0; i < n; i++)
    if (!c[i] && !er[i])
      c[i] = 1, dfs(i);

  for (int i = 0; i < n; i++)
    if (!er[i]) {
      if (c[i] == 1)
        addEdge(start, i);
      else
        addEdge(i, target);
    }

  printf("%d\n", ans + flow());
}


Fixed submission:
#include <bits/stdc++.h>
#include <stdio.h>

using namespace std;
typedef int ll;

const int N = 200005;

const int E = 2000006;
vector<int> g[N];

int ne;
struct Edge {
  int from, to;
  ll flow, cap;
} edge[E];

int lvl[N], vis[N], pass, start = N - 2, target = N - 1;
int qu[N], qt, px[N];

ll run(int s, int sink, ll minE) {
  if (s == sink)
    return minE;

  ll ans = 0;

  for (; px[s] < (int)g[s].size(); px[s]++) {
    int e = g[s][px[s]];
    auto &v = edge[e], &rev = edge[e ^ 1];
    if (lvl[v.to] != lvl[s] + 1 || v.flow >= v.cap)
      continue;
    ll tmp = run(v.to, sink, min(minE, v.cap - v.flow));
    v.flow += tmp, rev.flow -= tmp;
    ans += tmp, minE -= tmp;
    if (minE == 0)
      break;
  }
  return ans;
}

bool bfs(int source, int sink) {
  qt = 0;
  qu[qt++] = source;
  lvl[source] = 1;
  vis[source] = ++pass;

  for (int i = 0; i < qt; i++) {
    int u = qu[i];
    px[u] = 0;
    if (u == sink)
      return true;

    for (int e : g[u]) {
      auto v = edge[e];
      if (v.flow >= v.cap || vis[v.to] == pass)
        continue;
      vis[v.to] = pass;
      lvl[v.to] = lvl[u] + 1;
      qu[qt++] = v.to;
    }
  }
  return false;
}

ll flow(int source = start, int sink = target) {
  ll ans = 0;
  while (bfs(source, sink))
    ans += run(source, sink, N);
  return ans;
}

void addEdge(int u, int v, ll c = 1, ll rc = 0) {
  edge[ne] = {u, v, 0, c};
  g[u].push_back(ne++);
  edge[ne] = {v, u, 0, rc};
  g[v].push_back(ne++);
}

int c[N];
int er[N];
void dfs(int u) {

  for (int e : g[u]) {
    auto v = edge[e];
    if (er[v.to])
      continue;
    if (c[v.to] == c[u])
      assert(0);
    if (!c[v.to])
      c[v.to] = 3 - c[u], dfs(v.to);
  }
}

int n, v[N];

int deg[N];
// vector<pair<int, int>> edg;

map<int, vector<int>> cnt;
int build(int val) {
  int ans = 0;

  // cnt.clear();
  for (int i = 0; i < n; i++)
    if (!deg[i]) {
      if (cnt.count(val - v[i])) {
        int j;
        do {
          if (cnt[val - v[i]].empty()) {
            j = i;
            cnt.erase(val - v[i]);
            break;
          }
          j = cnt[val - v[i]].back();
          cnt[val - v[i]].pop_back();
          if (i == j) {
            if (!cnt[val - v[i]].empty()) {
              j = cnt[val - v[i]].back();
              cnt[val - v[i]].back() = i;
            } else {
              cnt[val - v[i]].push_back(i);
              break;
            }
          }
        } while (deg[j]);
        if (i == j)
          continue;
        if (cnt[val - v[i]].empty())
          cnt.erase(val - v[i]);
        deg[i]++, deg[j]++;
        // edge.emplace_back(j, i);
        ans++;
        // addEdge(i, j, 1, 1);
      }
      // else cnt[ v[i] ].push_back(i);
    }
  return ans;
}

int clean() {
  int ans = 0;

  queue<int> q;

  for (int i = 0; i < n; i++)
    if (deg[i] == 1) {
      q.push(i);
    }

  int u;
  while (!q.empty()) {
    u = q.front();
    q.pop();
    if (er[u])
      continue;
    int e = g[u][0];
    g[u].clear();
    ans++;
    er[u] = er[edge[e].to] = 1;
    for (int e2 : g[edge[e].to]) {
      if (er[edge[e2].to])
        continue;
      deg[edge[e2].to]--;
      edge[e2 ^ 1].cap = 0;
      if (deg[edge[e2].to] == 1) {
        q.push(edge[e2].to);
      }
    }
    g[edge[e].to].clear();
  }

  return ans;
}

int main() {

  scanf("%d", &n);

  for (int i = 0; i < n; i++)
    scanf("%d", v + i);

  for (int i = 0; i < n; i++)
    cnt[v[i]].push_back(i);

  int ans = 0;
  for (int i = 30; i >= 0; i--)
    ans += build(1 << i);

  printf("%d\n", ans);
  return 0;

  // int ans = clean();

  for (int i = 0; i < n; i++)
    if (!c[i] && !er[i])
      c[i] = 1, dfs(i);

  for (int i = 0; i < n; i++)
    if (!er[i]) {
      if (c[i] == 1)
        addEdge(start, i);
      else
        addEdge(i, target);
    }

  printf("%d\n", ans + flow());
}