Problem p01739 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
using Int = long long;

template <typename T1, typename T2> inline void chmin(T1 &a, T2 b) {
  if (a > b)
    a = b;
};
template <typename T1, typename T2> inline void chmax(T1 &a, T2 b) {
  if (a < b)
    a = b;
};

struct TopologicalSort {
  Int n;
  vector<vector<Int>> G;
  vector<bool> used;
  vector<Int> indeg, p;

  TopologicalSort() {}
  TopologicalSort(Int sz) : n(sz), G(n), used(n), indeg(n), p(0) {}

  void add_edge(Int s, Int t) { G[s].emplace_back(t); }

  void bfs(Int s) {
    queue<Int> q;
    q.push(s);
    used[s] = 1;
    while (!q.empty()) {
      Int v = q.front();
      q.pop();
      p.push_back(v);
      for (Int u : G[v]) {
        indeg[u]--;
        if (indeg[u] == 0 && !used[u]) {
          used[u] = 1;
          q.push(u);
        }
      }
    }
  }

  vector<Int> build() {
    fill(used.begin(), used.end(), 0);
    fill(indeg.begin(), indeg.end(), 0);

    for (Int i = 0; i < n; i++)
      for (Int v : G[i])
        indeg[v]++;

    for (Int i = 0; i < n; i++)
      if (indeg[i] == 0 && !used[i])
        bfs(i);
    return p;
  }
};

template <typename T> struct PrimalDual {
  struct edge {
    Int to;
    T cap, cost;
    Int rev;
    edge() {}
    edge(Int to, T cap, T cost, Int rev)
        : to(to), cap(cap), cost(cost), rev(rev) {}
  };

  T INF;
  vector<vector<edge>> G;
  vector<T> h, dist;
  vector<Int> prevv, preve;
  TopologicalSort ts;

  PrimalDual() {}
  PrimalDual(Int n, T INF)
      : INF(INF), G(n), h(n), dist(n), prevv(n), preve(n), ts(n) {}

  void add_edge(Int from, Int to, T cap, T cost) {
    G[from].emplace_back(to, cap, cost, G[to].size());
    G[to].emplace_back(from, 0, -cost, G[from].size() - 1);
    ts.add_edge(from, to);
  }

  T flow(Int s, Int t, Int f, Int &ok) {
    T res = 0;
    fill(h.begin(), h.end(), 0);

    {
      auto ord = ts.build();
      for (Int v : ord) {
        if (dist[v] == INF)
          continue;
        for (Int i = 0; i < (Int)G[v].size(); i++) {
          edge &e = G[v][i];
          if (e.cap == 0)
            continue;
          if (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;
          }
        }
      }
      for (Int v = 0; v < (Int)h.size(); v++)
        h[v] += dist[v];
    }

    while (f > 0) {
      // using P = pair<T, Int>;
      struct P {
        T first;
        Int second;
        P(T first, Int second) : first(first), second(second) {}
        bool operator<(const P &a) const { return first > a.first; }
      };

      priority_queue<P> que;
      fill(dist.begin(), dist.end(), INF);

      dist[s] = 0;
      que.emplace(dist[s], 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 < (Int)G[v].size(); i++) {
          edge &e = G[v][i];
          if (e.cap == 0)
            continue;
          if (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.emplace(dist[e.to], e.to);
          }
        }
      }
      if (dist[t] == INF)
        return ok = 0;
      for (Int v = 0; v < (Int)h.size(); v++)
        h[v] += dist[v];

      T 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;
      }
    }
    ok = 1;
    return res;
  }
};

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(0);

  Int n;
  cin >> n;
  const Int INF2 = 1e9;
  const Int INF3 = 1e15;
  PrimalDual<Int> G(n + 1, INF3);
  Int num = 0, ans = 0;
  for (Int i = 0; i < n; i++) {
    Int k;
    cin >> k;
    num += k;
    map<Int, Int> cnt;
    for (Int j = 0; j < k; j++) {
      Int t, c;
      cin >> t >> c;
      t--;
      cnt[t]++;
      ans += c + INF2;
      G.add_edge(i, t, INF2, c);
    }

    for (auto p : cnt)
      G.add_edge(i, p.first, p.second, -INF2);

    G.add_edge(i, n, INF2, 0);
  }

  Int ok = 1;
  ans += G.flow(0, n, INF2, ok);
  cout << ans << endl;
  assert(ok);
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using Int = long long;

template <typename T1, typename T2> inline void chmin(T1 &a, T2 b) {
  if (a > b)
    a = b;
};
template <typename T1, typename T2> inline void chmax(T1 &a, T2 b) {
  if (a < b)
    a = b;
};

struct TopologicalSort {
  Int n;
  vector<vector<Int>> G;
  vector<bool> used;
  vector<Int> indeg, p;

  TopologicalSort() {}
  TopologicalSort(Int sz) : n(sz), G(n), used(n), indeg(n), p(0) {}

  void add_edge(Int s, Int t) { G[s].emplace_back(t); }

  void bfs(Int s) {
    queue<Int> q;
    q.push(s);
    used[s] = 1;
    while (!q.empty()) {
      Int v = q.front();
      q.pop();
      p.push_back(v);
      for (Int u : G[v]) {
        indeg[u]--;
        if (indeg[u] == 0 && !used[u]) {
          used[u] = 1;
          q.push(u);
        }
      }
    }
  }

  vector<Int> build() {
    fill(used.begin(), used.end(), 0);
    fill(indeg.begin(), indeg.end(), 0);

    for (Int i = 0; i < n; i++)
      for (Int v : G[i])
        indeg[v]++;

    for (Int i = 0; i < n; i++)
      if (indeg[i] == 0 && !used[i])
        bfs(i);
    return p;
  }
};

template <typename T> struct RadixHeap {
  using uint = unsigned long long;
  vector<pair<uint, T>> v[65];
  uint size, last;

  RadixHeap() : size(0), last(0) {}

  bool empty() const { return size == 0; }

  inline Int getbit(Int a) { return a ? 64 - __builtin_clzll(a) : 0; }

  void push(uint key, const T &value) {
    ++size;
    v[getbit(key ^ last)].emplace_back(key, value);
  }

  pair<uint, T> pop() {
    if (v[0].empty()) {
      Int idx = 1;
      while (v[idx].empty())
        ++idx;
      last = min_element(begin(v[idx]), end(v[idx]))->first;
      for (auto &p : v[idx])
        v[getbit(p.first ^ last)].emplace_back(p);
      v[idx].clear();
    }
    --size;
    auto ret = v[0].back();
    v[0].pop_back();
    return ret;
  }
};

template <typename T> struct PrimalDual {
  struct edge {
    Int to;
    T cap, cost;
    Int rev;
    edge() {}
    edge(Int to, T cap, T cost, Int rev)
        : to(to), cap(cap), cost(cost), rev(rev) {}
  };

  T INF;
  vector<vector<edge>> G;
  vector<T> h, dist;
  vector<Int> prevv, preve;
  TopologicalSort ts;

  PrimalDual() {}
  PrimalDual(Int n, T INF)
      : INF(INF), G(n), h(n), dist(n), prevv(n), preve(n), ts(n) {}

  void add_edge(Int from, Int to, T cap, T cost) {
    G[from].emplace_back(to, cap, cost, G[to].size());
    G[to].emplace_back(from, 0, -cost, G[from].size() - 1);
    ts.add_edge(from, to);
  }

  T flow(Int s, Int t, Int f, Int &ok) {
    T res = 0;
    fill(h.begin(), h.end(), 0);

    {
      auto ord = ts.build();
      for (Int v : ord) {
        if (dist[v] == INF)
          continue;
        for (Int i = 0; i < (Int)G[v].size(); i++) {
          edge &e = G[v][i];
          if (e.cap == 0)
            continue;
          if (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;
          }
        }
      }
      for (Int v = 0; v < (Int)h.size(); v++)
        h[v] += dist[v];
    }

    while (f > 0) {
      RadixHeap<Int> que;
      fill(dist.begin(), dist.end(), INF);

      dist[s] = 0;
      que.push(dist[s], s);
      while (!que.empty()) {
        auto p = que.pop();
        Int v = p.second;
        if (dist[v] < p.first)
          continue;
        for (Int i = 0; i < (Int)G[v].size(); i++) {
          edge &e = G[v][i];
          if (e.cap == 0)
            continue;
          if (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(dist[e.to], e.to);
          }
        }
      }
      if (dist[t] == INF)
        return ok = 0;
      for (Int v = 0; v < (Int)h.size(); v++)
        h[v] += dist[v];

      T 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;
      }
    }
    ok = 1;
    return res;
  }
};

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(0);

  Int n;
  cin >> n;
  const Int INF1 = 1e5;
  const Int INF2 = 1e9;
  const Int INF3 = 1e15;
  PrimalDual<Int> G(n + 1, INF3);
  Int num = 0;
  for (Int i = 0; i < n; i++) {
    Int k;
    cin >> k;
    num += k;
    for (Int j = 0; j < k; j++) {
      Int t, c;
      cin >> t >> c;
      t--;
      G.add_edge(i, t, 1, c - INF2);
      G.add_edge(i, t, INF1, c);
    }
    G.add_edge(i, n, INF1, 0);
  }

  Int ok = 1;
  Int ans = INF2 * num + G.flow(0, n, INF1, ok);
  cout << ans << endl;
  assert(ok);
  return 0;
}