Problem p03020 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <array>
#include <climits>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>

struct Edge {
  int to, pair, flow;
  long long int cost;
  Edge(const int t, const int p, const int f, const long long int c)
      : to{t}, pair{p}, cost{c}, flow{f} {};
};
struct Coordinate {
  int x, y;
};
void add_edge(std::vector<std::vector<Edge>> &nodes, const int from,
              const int to, const int flow, const long long int cost) {
  nodes[from].emplace_back(to, nodes[to].size(), flow, cost);
  nodes[to].emplace_back(from, nodes[from].size() - 1, 0, -cost);
}
std::vector<std::vector<Edge>>
make_network(const std::vector<std::pair<Coordinate, int>> &reds,
             const std::vector<std::pair<Coordinate, int>> &blues) {
  const int mid = reds.size() + blues.size();
  const int source = mid + 4;
  const int drain = source + 1;
  std::vector<std::vector<Edge>> result(drain + 1);
  for (auto i = 0; i < reds.size(); ++i) {
    add_edge(result, source, i, reds[i].second, 0);
  }
  for (auto i = 0; i < blues.size(); ++i) {
    add_edge(result, i + reds.size(), drain, blues[i].second, 0);
  }
  for (auto t = 0; t < 4; ++t) {
    long long int x = ((t & 2) == 0) ? 1L : -1L;
    long long int y = ((t & 1) == 0) ? 1L : -1L;
    for (auto i = 0; i < reds.size(); ++i) {
      add_edge(result, i, mid + t, reds[i].second,
               2000000000LL + x * reds[i].first.x + y * reds[i].first.y);
      add_edge(result, mid + t, i + reds.size(), blues[i].second,
               2000000000LL - x * blues[i].first.x - y * blues[i].first.y);
    }
  }
  return result;
}
long long int cal_min_cost_maxflow(std::vector<std::vector<Edge>> nodes) {
  const int source = nodes.size() - 2;
  const int drain = source + 1;
  std::vector<long long int> potential(nodes.size(), 0),
      min_cost(nodes.size(), LLONG_MAX);
  std::vector<Edge *> prev(nodes.size(), nullptr);
  std::priority_queue<std::pair<long long int, int>,
                      std::vector<std::pair<long long int, int>>,
                      std::function<bool(const std::pair<long long int, int>,
                                         const std::pair<long long int, int>)>>
      queue([](const std::pair<long long int, int> a,
               const std::pair<long long int, int> b) {
        return a.first > b.first;
      });
  long long int result = 0L;
  while (true) {
    min_cost[source] = 0;
    queue.emplace(0, source);
    while (!queue.empty()) {
      auto cost = queue.top().first;
      auto current = queue.top().second;
      queue.pop();
      if (min_cost[current] == cost && current != drain) {
        for (const auto &next : nodes[current])
          if (next.flow > 0) {
            if (min_cost[next.to] >
                potential[next.to] + cost + next.cost - potential[current]) {
              min_cost[next.to] =
                  potential[next.to] + cost + next.cost - potential[current];
              prev[next.to] = &nodes[next.to][next.pair];
              queue.emplace(min_cost[next.to], next.to);
            }
          }
      }
    }
    if (min_cost[drain] == LLONG_MAX)
      return result;
    auto last = drain;
    auto min_flow = INT_MAX;
    while (last != source) {
      min_flow =
          std::min(nodes[prev[last]->to][prev[last]->pair].flow, min_flow);
      last = prev[last]->to;
    }
    result += min_flow * min_cost[drain];
    last = drain;
    while (last != source) {
      auto e = prev[last];
      e->flow += min_flow;
      nodes[e->to][e->pair].flow -= min_flow;
      last = e->to;
    }
    for (auto i = 0; i < nodes.size(); ++i) {
      if (i != drain && min_cost[i] != LLONG_MAX)
        potential[i] += min_cost[i];
    }
    std::fill(min_cost.begin(), min_cost.end(), LLONG_MAX);
  }
}
int main() {
  int n;
  std::cin >> n;
  std::vector<std::pair<Coordinate, int>> reds(n), blues(n);
  for (auto &r : reds)
    std::cin >> r.first.x >> r.first.y >> r.second;
  for (auto &b : blues)
    std::cin >> b.first.x >> b.first.y >> b.second;
  long long int count = 0LL;
  for (const auto r : reds)
    count += r.second;
  std::cout << count * 4000000000LL -
                   cal_min_cost_maxflow(make_network(reds, blues))
            << std::endl;
}

Fixed submission:
#include <algorithm>
#include <array>
#include <climits>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>

struct Edge {
  int to, pair, flow;
  long long int cost;
  Edge(const int t, const int p, const int f, const long long int c)
      : to{t}, pair{p}, cost{c}, flow{f} {};
};
struct Coordinate {
  int x, y;
};
void add_edge(std::vector<std::vector<Edge>> &nodes, const int from,
              const int to, const int flow, const long long int cost) {
  nodes[from].emplace_back(to, nodes[to].size(), flow, cost);
  nodes[to].emplace_back(from, nodes[from].size() - 1, 0, -cost);
}
std::vector<std::vector<Edge>>
make_network(const std::vector<std::pair<Coordinate, int>> &reds,
             const std::vector<std::pair<Coordinate, int>> &blues) {
  const int mid = reds.size() + blues.size();
  const int source = mid + 4;
  const int drain = source + 1;
  std::vector<std::vector<Edge>> result(drain + 1);
  for (auto i = 0; i < reds.size(); ++i) {
    add_edge(result, source, i, reds[i].second, 0);
  }
  for (auto i = 0; i < blues.size(); ++i) {
    add_edge(result, i + reds.size(), drain, blues[i].second, 0);
  }
  for (auto t = 0; t < 4; ++t) {
    long long int x = ((t & 2) == 0) ? 1L : -1L;
    long long int y = ((t & 1) == 0) ? 1L : -1L;
    for (auto i = 0; i < reds.size(); ++i) {
      add_edge(result, i, mid + t, reds[i].second,
               2000000000LL + x * reds[i].first.x + y * reds[i].first.y);
      add_edge(result, mid + t, i + reds.size(), blues[i].second,
               2000000000LL - x * blues[i].first.x - y * blues[i].first.y);
    }
  }
  return result;
}
long long int cal_min_cost_maxflow(std::vector<std::vector<Edge>> nodes) {
  const int source = nodes.size() - 2;
  const int drain = source + 1;
  std::vector<long long int> potential(nodes.size(), 0),
      min_cost(nodes.size(), LLONG_MAX);
  std::vector<Edge *> prev(nodes.size(), nullptr);
  std::priority_queue<std::pair<long long int, int>,
                      std::vector<std::pair<long long int, int>>,
                      std::function<bool(const std::pair<long long int, int>,
                                         const std::pair<long long int, int>)>>
      queue([](const std::pair<long long int, int> a,
               const std::pair<long long int, int> b) {
        return a.first > b.first;
      });
  long long int result = 0L;
  while (true) {
    min_cost[source] = 0;
    queue.emplace(0, source);
    while (!queue.empty()) {
      auto cost = queue.top().first;
      auto current = queue.top().second;
      queue.pop();
      if (min_cost[current] == cost && current != drain) {
        for (const auto &next : nodes[current])
          if (next.flow > 0) {
            if (min_cost[next.to] >
                potential[next.to] + cost + next.cost - potential[current]) {
              min_cost[next.to] =
                  potential[next.to] + cost + next.cost - potential[current];
              prev[next.to] = &nodes[next.to][next.pair];
              queue.emplace(min_cost[next.to], next.to);
            }
          }
      }
    }
    if (min_cost[drain] == LLONG_MAX)
      return result;
    auto last = drain;
    auto min_flow = INT_MAX;
    while (last != source) {
      min_flow =
          std::min(nodes[prev[last]->to][prev[last]->pair].flow, min_flow);
      last = prev[last]->to;
    }
    result += min_flow * min_cost[drain];
    last = drain;
    while (last != source) {
      auto e = prev[last];
      e->flow += min_flow;
      nodes[e->to][e->pair].flow -= min_flow;
      last = e->to;
    }
    for (auto i = 0; i < nodes.size(); ++i) {
      if (i != drain && min_cost[i] != LLONG_MAX)
        potential[i] -= min_cost[i];
    }
    std::fill(min_cost.begin(), min_cost.end(), LLONG_MAX);
  }
}
int main() {
  int n;
  std::cin >> n;
  std::vector<std::pair<Coordinate, int>> reds(n), blues(n);
  for (auto &r : reds)
    std::cin >> r.first.x >> r.first.y >> r.second;
  for (auto &b : blues)
    std::cin >> b.first.x >> b.first.y >> b.second;
  long long int count = 0LL;
  for (const auto r : reds)
    count += r.second;
  std::cout << count * 4000000000LL -
                   cal_min_cost_maxflow(make_network(reds, blues))
            << std::endl;
}