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

#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define IINF (INT_MAX)
#define LLINF (LLONG_MAX)
#define MAX_V 10000

using namespace std;

typedef long long ll;

typedef pair<ll, ll> P;
struct edge {
  ll to, cap, cost, rev;
  edge(ll to = LLINF, ll cap = LLINF, ll cost = LLINF, ll rev = LLINF)
      : to(to), cap(cap), cost(cost), rev(rev) {}
};
int V;
vector<edge> G[MAX_V];
ll h[MAX_V], dist[MAX_V], prevv[MAX_V], preve[MAX_V];

void add_edge(ll from, ll to, ll cap, ll cost) {
  G[from].push_back(edge(to, cap, cost, (ll)G[to].size()));
  G[to].push_back(edge(from, 0, -cost, (ll)G[from].size() - 1));
}

ll min_cost_flow(ll s, ll t, ll f) {
  ll res = 0;
  rep(i, V) h[i] = 0;
  while (f > 0) {
    priority_queue<P, vector<P>, greater<P>> que;
    rep(i, V) dist[i] = LLINF;
    dist[s] = 0;
    que.push(P(0, s));
    while (!que.empty()) {
      P p = que.top();
      que.pop();
      ll v = p.second;
      if (dist[v] < p.first)
        continue;
      for (int i = 0; i < G[v].size(); i++) {
        edge &e = G[v][i];
        if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
          dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
          prevv[e.to] = v;
          preve[e.to] = i;
          que.push(P(dist[e.to], e.to));
        }
      }
    }
    if (dist[t] == LLINF)
      return -1;
    for (int v = 0; v < V; v++)
      h[v] += dist[v];
    ll d = f;
    for (int v = t; v != s; v = prevv[v])
      d = min(d, G[prevv[v]][preve[v]].cap);
    f -= d;
    res += d * h[t];
    for (int v = t; v != s; v = prevv[v]) {
      edge &e = G[prevv[v]][preve[v]];
      e.cap -= d;
      G[v][e.rev].cap += d;
    }
  }
  return res;
}

int main() {
  int N;
  cin >> N;
  int *A = new int[N];
  int *B = new int[N];
  map<int, int> getIndex;
  int dex = 0;
  rep(i, N) {
    cin >> A[i] >> B[i];
    if (getIndex.find(A[i]) == getIndex.end())
      getIndex[A[i]] = dex++;
    if (getIndex.find(B[i]) == getIndex.end())
      getIndex[B[i]] = dex++;
  }
  V = N + (int)getIndex.size();
  int source = V, sink = source + 1, grave = sink + 1;
  V += 3;
  add_edge(grave, sink, LLINF, 0);
  rep(i, N) add_edge(source, i, 1, 0);
  rep(i, (int)getIndex.size()) add_edge(N + i, sink, 1, 0);
  rep(i, N) {
    int to1 = getIndex[A[i]] + N;
    int to2 = getIndex[B[i]] + N;
    add_edge(i, to1, 1, -B[i]);
    add_edge(i, to2, 1, -A[i]);
    add_edge(i, grave, LLINF, 0);
  }
  delete[] A;
  delete[] B;
  cout << -min_cost_flow(source, sink, N) << endl;

  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define IINF (INT_MAX)
#define MAX_V 3000

using namespace std;

typedef pair<int, int> P;
struct edge {
  int to, cap, cost, rev;
  edge(int to = IINF, int cap = IINF, int cost = IINF, int rev = IINF)
      : to(to), cap(cap), cost(cost), rev(rev) {}
};
int V;
vector<edge> G[MAX_V];
int h[MAX_V], dist[MAX_V], prevv[MAX_V], preve[MAX_V];

void add_edge(int from, int to, int cap, int cost) {
  G[from].push_back(edge(to, cap, cost, (int)G[to].size()));
  G[to].push_back(edge(from, 0, -cost, (int)G[from].size() - 1));
}

int min_cost_flow(int s, int t, int f) {
  int res = 0;
  rep(i, V) h[i] = 0;
  while (f > 0) {
    priority_queue<P, vector<P>, greater<P>> que;
    rep(i, V) dist[i] = IINF;
    dist[s] = 0;
    que.push(P(0, s));
    while (!que.empty()) {
      P p = que.top();
      que.pop();
      int v = p.second;
      if (dist[v] < p.first)
        continue;
      for (int i = 0; i < G[v].size(); i++) {
        edge &e = G[v][i];
        if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
          dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
          prevv[e.to] = v;
          preve[e.to] = i;
          que.push(P(dist[e.to], e.to));
        }
      }
    }
    if (dist[t] == IINF)
      break;
    for (int v = 0; v < V; v++)
      h[v] += dist[v];
    int d = f;
    for (int v = t; v != s; v = prevv[v])
      d = min(d, G[prevv[v]][preve[v]].cap);
    f -= d;
    res += d * h[t];
    for (int v = t; v != s; v = prevv[v]) {
      edge &e = G[prevv[v]][preve[v]];
      e.cap -= d;
      G[v][e.rev].cap += d;
    }
  }
  return res;
}

int main() {
  int N;
  cin >> N;
  int *A = new int[N];
  int *B = new int[N];
  map<int, int> getIndex;
  int dex = 0;
  rep(i, N) {
    cin >> A[i] >> B[i];
    if (getIndex.find(A[i]) == getIndex.end())
      getIndex[A[i]] = dex++;
    if (getIndex.find(B[i]) == getIndex.end())
      getIndex[B[i]] = dex++;
  }
  V = N + (int)getIndex.size();
  int source = V, sink = source + 1, grave = sink + 1;
  V += 3;
  add_edge(grave, sink, 1, 0);
  rep(i, N) add_edge(source, i, 1, 0);
  rep(i, (int)getIndex.size()) add_edge(N + i, sink, 1, 0);
  rep(i, N) {
    int to1 = getIndex[A[i]] + N;
    int to2 = getIndex[B[i]] + N;
    add_edge(i, to1, 1, -B[i]);
    add_edge(i, to2, 1, -A[i]);
    add_edge(i, grave, 1, 0);
  }
  delete[] A;
  delete[] B;
  cout << -min_cost_flow(source, sink, N) << endl;

  return 0;
}