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

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

struct Edge {
  int to;
  Weight cap, rev;
  Weight cost;
};

using Edges = vector<Edge>;
using Graph = vector<Edges>;

class Flow {
  const Weight INF = 1e9 + 7;
  const bool isNegative = false;
  int N;
  Graph g;
  vector<int> level;
  vector<int> iter;
  void bfs(int s);
  Weight dfs(int v, int t, Weight f);

public:
  Flow(int N) : N(N), g(N){};
  void addEdge(int from, int to, Weight cap);
  void addEdge(int from, int to, Weight cap, Weight cost);
  Weight maxFlow(int s, int t);
  Weight minCostFlow(int s, int t, Weight f);
};

void Flow::addEdge(int from, int to, Weight cap) {
  g[from].push_back({to, cap, int(g[to].size()), 0});
  g[to].push_back({from, Weight(0), int(g[from].size()) - 1, 0});
}

void Flow::addEdge(int from, int to, Weight cap, Weight cost) {
  g[from].push_back({to, cap, int(g[to].size()), cost});
  g[to].push_back({from, Weight(0), int(g[from].size()) - 1, -cost});
}
Weight Flow::maxFlow(int s, int t) {
  Weight flow = 0;
  while (true) {
    bfs(s);
    if (level[t] < 0)
      return flow;
    iter.assign(N, 0);
    Weight f;
    while ((f = dfs(s, t, INF)) > 0) {
      flow += f;
    }
  }
}
void Flow::bfs(int s) {
  level.assign(N, -1);
  queue<int> que;
  level[s] = 0;
  que.push(s);
  while (!que.empty()) {
    int v = que.front();
    que.pop();
    for (int i = 0; i < g[v].size(); i++) {
      Edge &e = g[v][i];
      if (e.cap > 0 && level[e.to] < 0) {
        level[e.to] = level[v] + 1;
        que.push(e.to);
      }
    }
  }
}

Weight Flow::dfs(int v, int t, Weight f) {
  if (v == t)
    return f;
  for (int &i = iter[v]; i < g[v].size(); i++) {
    Edge &e = g[v][i];
    if (e.cap > 0 && level[v] < level[e.to]) {
      Weight d = dfs(e.to, t, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        g[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}

Weight Flow::minCostFlow(int s, int t, Weight f) {
  using P = pair<Weight, int>;
  Weight res = 0;
  vector<Weight> h(N, 0);
  vector<int> used(N), preve(N), prevv(N);
  vector<Weight> dist(N);
  while (f > 0) {
    fill(dist.begin(), dist.end(), INF);
    dist[s] = 0;
    if (!isNegative) {
      // Dijkstra
      fill(used.begin(), used.end(), 0);
      priority_queue<P, vector<P>, greater<P>> que;
      que.push(make_pair(Weight(0), s));
      while (!que.empty()) {
        P p = que.top();
        que.pop();
        int v = p.second;
        if (used[v])
          continue;
        used[v] = true;
        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(make_pair(dist[e.to], e.to));
          }
        }
      }
    } else {
      // Bermanford
      bool update = true;
      while (update) {
        update = false;
        for (int v = 0; v < N; v++) {
          if (dist[v] == INF)
            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) {
              dist[e.to] = dist[v] + e.cost;
              prevv[e.to] = v;
              preve[e.to] = i;
              update = true;
            }
          }
        }
      }
    }

    if (dist[t] == INF) {
      return -1;
    }
    if (!isNegative) {
      for (int v = 0; v < N; v++)
        h[v] += dist[v];
    }
    Weight d = f;
    for (int v = t; v != s; v = prevv[v]) {
      d = min(d, g[prevv[v]][preve[v]].cap);
    }
    f -= d;
    if (!isNegative) {
      res += d * h[t];
    } else {
      res += d * dist[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;
}

const int INF = 1e9;
const int LSIZE = 1000;
struct Query {
  int p, t;
};
bool operator<(Query lhs, Query rhs) { return lhs.t < rhs.t; }
int solve(int n, int m, int l) {
  vector<vector<int>> d(n, vector<int>(n, INF));
  for (int i = 0; i < n; i++)
    d[i][i] = 0;

  for (int i = 0; i < m; i++) {
    int u, v, tmp;
    cin >> u >> v >> tmp;
    d[u][v] = d[v][u] = tmp;
  }
  vector<Query> q(l);
  for (int i = 0; i < l; i++)
    cin >> q[i].p >> q[i].t;
  sort(q.begin(), q.end());

  for (int k = 0; k < n; k++) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
      }
    }
  }
  using Bit = bitset<LSIZE>;
  vector<Bit> reachable(l);
  vector<pair<int, int>> dag;
  for (int i = l - 1; i >= 0; i--) {
    for (int j = i + 1; j < l; j++) {
      if (reachable[i][j])
        continue;
      if (q[j].t - q[i].t >= d[q[i].p][q[j].p]) {
        reachable[i][j] = true;
        reachable[i] |= reachable[j];
        dag.push_back(make_pair(i, j));
      }
    }
  }

  Flow flow(2 * l + 4);
  const int S0 = 2 * l;
  const int S1 = 2 * l + 1;
  const int T1 = 2 * l + 2;
  const int T0 = 2 * l + 3;
  auto in = [&](int x) { return x; };
  auto out = [&](int x) { return l + x; };

  const int A = 0;
  const int B = 1;
  const int C = 10;
  flow.addEdge(S0, S1, n, 0);
  flow.addEdge(T1, T0, n, 0);
  for (int i = 0; i < l; i++) {
    flow.addEdge(S1, in(i), n, B);
  }
  flow.addEdge(S1, T1, n, A);
  for (auto e : dag) {
    flow.addEdge(out(e.first), in(e.second), n, 0);
  }
  for (int i = 0; i < l; i++) {
    flow.addEdge(in(i), out(i), n, 0);
  }
  for (int i = 0; i < l; i++) {
    flow.addEdge(out(i), in(i), 1, C);
    flow.addEdge(S0, out(i), 1, 0);
    flow.addEdge(in(i), T0, 1, 0);
  }
  for (int i = 0; i < l; i++) {
    flow.addEdge(out(i), T1, n, 0);
  }
  int sumc = flow.minCostFlow(S0, T0, n + l);
  sumc -= C * l;
  int res = sumc + C * l - A * n;
  cout << res << endl;

  return 0;
}

int main() {
  int n, m, l;
  while (cin >> n >> m >> l, n) {
    solve(n, m, l);
  }
  return 0;
}


Error: TLE

Fixed submission:

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

struct Edge {
  int to;
  Weight cap, rev;
  Weight cost;
};

using Edges = vector<Edge>;
using Graph = vector<Edges>;
Weight INF = 1e9;
class Flow {
  const Weight INF = 1e9 + 7;
  const bool isNegative = false;
  int N;
  Graph g;
  vector<int> level;
  vector<int> iter;
  void bfs(int s);
  Weight dfs(int v, int t, Weight f);

public:
  Flow(int N) : N(N), g(N){};
  void addEdge(int from, int to, Weight cap);
  void addEdge(int from, int to, Weight cap, Weight cost);
  Weight maxFlow(int s, int t);
  Weight minCostFlow(int s, int t, Weight f);
};

void Flow::addEdge(int from, int to, Weight cap) {
  g[from].push_back({to, cap, int(g[to].size()), 0});
  g[to].push_back({from, Weight(0), int(g[from].size()) - 1, 0});
}

void Flow::addEdge(int from, int to, Weight cap, Weight cost) {
  g[from].push_back({to, cap, int(g[to].size()), cost});
  g[to].push_back({from, Weight(0), int(g[from].size()) - 1, -cost});
}
Weight Flow::maxFlow(int s, int t) {
  Weight flow = 0;
  while (true) {
    bfs(s);
    if (level[t] < 0)
      return flow;
    iter.assign(N, 0);
    Weight f;
    while ((f = dfs(s, t, INF)) > 0) {
      flow += f;
    }
  }
}
void Flow::bfs(int s) {
  level.assign(N, -1);
  queue<int> que;
  level[s] = 0;
  que.push(s);
  while (!que.empty()) {
    int v = que.front();
    que.pop();
    for (int i = 0; i < g[v].size(); i++) {
      Edge &e = g[v][i];
      if (e.cap > 0 && level[e.to] < 0) {
        level[e.to] = level[v] + 1;
        que.push(e.to);
      }
    }
  }
}

Weight Flow::dfs(int v, int t, Weight f) {
  if (v == t)
    return f;
  for (int &i = iter[v]; i < g[v].size(); i++) {
    Edge &e = g[v][i];
    if (e.cap > 0 && level[v] < level[e.to]) {
      Weight d = dfs(e.to, t, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        g[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}

Weight Flow::minCostFlow(int s, int t, Weight f) {
  using P = pair<Weight, int>;
  Weight res = 0;
  vector<Weight> h(N, 0);
  vector<int> used(N), preve(N), prevv(N);
  vector<Weight> dist(N);
  while (f > 0) {
    fill(dist.begin(), dist.end(), INF);
    dist[s] = 0;
    if (!isNegative) {
      // Dijkstra
      fill(used.begin(), used.end(), 0);
      priority_queue<P, vector<P>, greater<P>> que;
      que.push(make_pair(Weight(0), s));
      while (!que.empty()) {
        P p = que.top();
        que.pop();
        int v = p.second;
        if (used[v])
          continue;
        used[v] = true;
        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(make_pair(dist[e.to], e.to));
          }
        }
      }
    } else {
      // Bermanford
      bool update = true;
      while (update) {
        update = false;
        for (int v = 0; v < N; v++) {
          if (dist[v] == INF)
            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) {
              dist[e.to] = dist[v] + e.cost;
              prevv[e.to] = v;
              preve[e.to] = i;
              update = true;
            }
          }
        }
      }
    }

    if (dist[t] == INF) {
      return -1;
    }
    if (!isNegative) {
      for (int v = 0; v < N; v++)
        h[v] += dist[v];
    }
    Weight d = f;
    for (int v = t; v != s; v = prevv[v]) {
      d = min(d, g[prevv[v]][preve[v]].cap);
    }
    f -= d;
    if (!isNegative) {
      res += d * h[t];
    } else {
      res += d * dist[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 solve();
int main() {
  while (solve()) {
  }
  return true;
}
int solve() {
  int n, m, l;
  cin >> n >> m >> l;
  if (n == 0)
    return false;
  vector<vector<int>> d(n, vector<int>(n, INF));
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    int dd;
    cin >> dd;
    d[u][v] = dd;
    d[v][u] = dd;
  }
  for (int k = 0; k < n; k++) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
      }
    }
  }
  vector<int> p(l), t(l);
  for (int i = 0; i < l; i++)
    cin >> p[i] >> t[i];
  vector<pair<int, int>> tp(l);
  for (int i = 0; i < l; i++)
    tp[i] = {t[i], p[i]};
  sort(tp.begin(), tp.end());
  for (int i = 0; i < l; i++) {
    t[i] = tp[i].first;
    p[i] = tp[i].second;
  }

  Flow org(2 * l + 4);
  //[0,l):in
  int S = 2 * l;
  int superS = 2 * l + 1;
  int T = 2 * l + 2;
  int superT = 2 * l + 3;

  for (int i = 0; i < l; i++) {
    org.addEdge(S, i, 1, 0);
    org.addEdge(i + l, T, INF, 0);
    // org.addEdge(i,i+l,1,-1);
    org.addEdge(i + l, i, 1, 1);
    org.addEdge(superS, i + l, 1, 0);
    org.addEdge(i, superT, 1, 0);
  }

  for (int i = 0; i < l; ++i) {
    vector<int> town(n, false);
    vector<int> index;
    for (int j = i + 1; j < l; j++) {
      if (town[p[j]] || d[p[i]][p[j]] > t[j] - t[i])
        continue;
      town[p[j]] = true;
      index.push_back(j);
    }
    for (int j = 0; j < index.size(); j++) {
      bool isok = true;
      for (int k = 0; k < j; k++) {
        if (d[p[index[j]]][p[index[k]]] <= t[index[k]] - t[index[j]])
          isok = false;
      }
      if (isok) {
        org.addEdge(l + i, index[j], 1, 0);
        org.addEdge(l + i, index[j] + l, INF, 0);
      }
    }
  }

  org.addEdge(superS, S, l, 0);
  org.addEdge(T, superT, l, 0);
  org.addEdge(S, T, n, 0);
  int cost = org.minCostFlow(superS, superT, l + l);
  cost -= l * 1000;
  cout << cost << endl;

  return true;
}