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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;

#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define FOREQ(i, k, n) for (int i = (k); i <= (int)(n); ++i)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

#define SZ(v) (int)((v).size())
#define MEMSET(v, h) memset((v), (h), sizeof(v))
#define FIND(m, w) ((m).find(w) != (m).end())

typedef int Weight;
struct Edge {
  int index;
  int src;
  int dest;
  Weight weight;
  Edge(int index, int src, int dest, Weight weight)
      : index(index), src(src), dest(dest), weight(weight) {
    ;
  }
  bool operator<(const Edge &rhs) const {
    if (weight != rhs.weight) {
      return weight > rhs.weight;
    }
    if (src != rhs.src) {
      return src < rhs.src;
    }
    return dest < rhs.dest;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void PrintMatrix(const Matrix &matrix) {
  for (int y = 0; y < (int)matrix.size(); y++) {
    for (int x = 0; x < (int)matrix[y].size(); x++) {
      printf("%d ", matrix[y][x]);
    }
    puts("");
  }
}

Weight augment(const Graph &g, Array &capacity, const vector<int> &level,
               vector<bool> &finished, int from, int t, Weight cur) {
  if (from == t || cur == 0) {
    return cur;
  }
  if (finished[from]) {
    return 0;
  }
  for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
    int to = it->dest;
    if (level[to] != level[from] + 1) {
      continue;
    }
    Weight f = augment(g, capacity, level, finished, to, t,
                       min(cur, capacity[it->index]));
    if (f > 0) {
      capacity[it->index] -= f;
      capacity[it->index ^ 1] += f;
      return f;
    }
  }
  finished[from] = true;
  return 0;
}

// index^1 is reverse edge
Weight MaxFlow(const Graph &g, int e, int s, int t) {
  int n = g.size();
  Array capacity(e);
  for (int from = 0; from < n; from++) {
    for (Edges::const_iterator it = g[from].begin(); it != g[from].end();
         it++) {
      capacity[it->index] += it->weight;
    }
  }
  int ans = 0;
  while (true) {
    vector<int> level(n, -1);
    level[s] = 0;
    queue<int> que;
    que.push(s);
    for (int d = n; !que.empty() && level[que.front()] < d;) {
      int from = que.front();
      que.pop();
      if (from == t) {
        d = level[from];
      }
      for (Edges::const_iterator it = g[from].begin(); it != g[from].end();
           it++) {
        int to = it->dest;
        if (capacity[it->index] > 0 && level[to] == -1) {
          que.push(to);
          level[to] = level[from] + 1;
        }
      }
    }
    vector<bool> finished(n);
    bool end = true;
    while (true) {
      Weight f = augment(g, capacity, level, finished, s, t, 2000000000LL);
      if (f == 0) {
        break;
      }
      ans += f;
      end = false;
    }
    if (end) {
      break;
    }
  }
  return ans;
}

void addEdge(int &e, Graph &g, int from, int to) {
  g[from].push_back(Edge(e++, from, to, 1));
  g[to].push_back(Edge(e++, to, from, 0));
}

int n, m, l;
inline int IN(int x) { return 2 * x; }
inline int OUT(int x) { return 2 * x + 1; }
inline int SOURCE() { return 2 * l; }
inline int DEST() { return 2 * l + 1; }
inline int SIZE() { return 2 * l + 2; }

ll matrix[110][110];
int point[1010];
ll ontime[1010];
bool visit[2020];

int main() {
  while (scanf("%d %d %d", &n, &m, &l), n | m | l) {
    int e = 0;
    MEMSET(matrix, 0x0f);
    Graph g(2 * l + 2);
    REP(i, m) {
      int f, t, c;
      scanf("%d %d %d", &f, &t, &c);
      matrix[f][t] = min(matrix[f][t], (ll)c);
      matrix[t][f] = min(matrix[t][f], (ll)c);
    }
    REP(k, n) REP(i, n) REP(j, n) {
      matrix[j][j] = 0;
      matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);
    }
    REP(i, l) {
      int p, t;
      scanf("%d %d", &p, &t);
      point[i] = p;
      ontime[i] = t;
    }
    REP(i, l) {
      addEdge(e, g, SOURCE(), IN(i));
      addEdge(e, g, OUT(i), DEST());
      REP(j, l) {
        if (i == j) {
          continue;
        }
        if (ontime[j] + matrix[point[j]][point[i]] <= ontime[i]) {
          addEdge(e, g, IN(i), OUT(j));
        }
      }
    }
    printf("%d\\n", l - MaxFlow(g, e, SOURCE(), DEST()));
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;

#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define FOREQ(i, k, n) for (int i = (k); i <= (int)(n); ++i)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

#define SZ(v) (int)((v).size())
#define MEMSET(v, h) memset((v), (h), sizeof(v))
#define FIND(m, w) ((m).find(w) != (m).end())

typedef int Weight;
struct Edge {
  int src;
  int dest;
  int capacity;
  Weight weight;
  Edge() { ; }
  Edge(int src, int dest, int capacity, Weight weight)
      : src(src), dest(dest), capacity(capacity), weight(weight) {
    ;
  }
  bool operator<(const Edge &rhs) const { return weight > rhs.weight; }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void printMatrix(const Matrix &matrix) {
  REP(y, matrix.size()) {
    REP(x, matrix[y].size()) { printf("%d ", matrix[y][x]); }
    puts("");
  }
}

/*
Weight augment(const Graph &g, Matrix &capacity, const vector<int> &level,
vector<bool> &finished, int from, int t, Weight cur) { if (from == t || cur ==
0) { return cur; } if (finished[from]) { return 0; } FORIT(it, g[from]) { int to
= it->dest; if (level[to] <= level[from]) { continue; } Weight f = augment(g,
capacity, level, finished, to, t, min(cur, capacity[from][to])); if (f > 0) {
            capacity[from][to] -= f;
            capacity[to][from] += f;
            return f;
        }
    }
    finished[from] = true;
    return 0;
}

Weight MaxFlow(const Graph &g, int s, int t) {
    const int n = g.size();
    Matrix capacity(n, Array(n));
    REP(from, n) {
        FORIT(it, g[from]) {
            int to = it->dest;
            capacity[from][to] += it->weight;
        }
    }
    int ans = 0;
    while (true) {
        vector<int> level(n, -1);
        level[s] = 0;
        queue<int> que;
        que.push(s);
        for (int d = n; !que.empty() && level[que.front()] < d; ) {
            const int from = que.front();
            que.pop();
            if (from == t) { d = level[from]; }
            FORIT(it, g[from]) {
                int to = it->dest;
                if (capacity[from][to] > 0 && level[to] == -1) {
                    que.push(to);
                    level[to] = level[from] + 1;
                }
            }
        }
        vector<bool> finished(n);
        bool end = true;
        while (true) {
            Weight f = augment(g, capacity, level, finished, s, t,
2000000000LL); if (f == 0) { break; } ans += f; end = false;
        }
        if (end) { break; }
    }
    return ans;
}
*/

int parent[2020];
int nowDist[2020];
int prevDist[2020];

int MinCostFlow(const Graph &g, int s, int t, int l) {
  const int n = g.size();
  Matrix capacity(n, Array(n, 0));
  Matrix cost(n, Array(n, 0));
  REP(from, n) {
    FORIT(it, g[from]) {
      assert(it->capacity >= 0);
      capacity[from][it->dest] += it->capacity;
      cost[from][it->dest] += it->weight;
    }
  }

  vector<int> parent(n);
  vector<int> prev_dist(n, 0);
  vector<int> now_dist(n);

  // calc potential
  REP(iter, n) {
    bool end = true;
    REP(from, n) {
      FORIT(it, g[from]) {
        int to = it->dest;
        if (capacity[from][to] == 0) {
          continue;
        }
        int ncost = prev_dist[from] + cost[from][to];
        if (ncost < prev_dist[to]) {
          end = false;
          prev_dist[to] = ncost;
        }
      }
    }
    if (end) {
      break;
    }
  }

  int ret = 0;
  int c = 0;
  while (true) {
    ret++;
    fill(parent.begin(), parent.end(), -1);
    fill(now_dist.begin(), now_dist.end(), 2000000000LL);
    priority_queue<Edge> que;
    que.push(Edge(s, s, 0, 0));
    now_dist[s] = 0;
    while (!que.empty()) {
      Edge node = que.top();
      que.pop();
      if (parent[node.dest] != -1) {
        continue;
      }
      parent[node.dest] = node.src;
      int from = node.dest;
      FORIT(it, g[from]) {
        int to = it->dest;
        int ncost =
            node.weight + cost[from][to] + (prev_dist[from] - prev_dist[to]);
        if (capacity[from][to] == 0) {
          continue;
        }
        if (ncost >= now_dist[to]) {
          continue;
        }
        now_dist[to] = ncost;
        que.push(Edge(from, to, 0, ncost));
      }
    }
    if (parent[t] == -1) {
      assert(false);
    }
    int from = parent[t];
    int to = t;
    while (from != to) {
      c += cost[from][to];
      capacity[from][to]--;
      capacity[to][from]++;
      from = parent[from];
      to = parent[to];
    }
    REP(i, n) { prev_dist[i] += now_dist[i]; }
    if (c == -l) {
      return ret;
    }
  }
  assert(false);
  return 0;
}

void addEdge(Graph &g, int from, int to, int cost) {
  g[from].push_back(Edge(from, to, 1, cost));
  g[to].push_back(Edge(to, from, 0, -cost));
}

int n, m, l;
inline int IN(int x) { return 2 * x; }
inline int OUT(int x) { return 2 * x + 1; }
inline int SOURCE() { return 2 * l; }
inline int DEST() { return 2 * l + 1; }
inline int SIZE() { return 2 * l + 2; }

ll matrix[110][110];
int point[1010];
ll ontime[1010];
bool visit[2020];

int main() {
  while (scanf("%d %d %d", &n, &m, &l), n | m | l) {
    MEMSET(matrix, 0x0f);
    Graph g(2 * l + 2);
    REP(i, m) {
      int f, t, c;
      scanf("%d %d %d", &f, &t, &c);
      matrix[f][t] = c;
      matrix[t][f] = c;
    }
    REP(k, n) REP(i, n) REP(j, n) {
      matrix[j][j] = 0;
      matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);
    }
    REP(i, l) {
      int p, t;
      scanf("%d %d", &p, &t);
      point[i] = p;
      ontime[i] = t;
    }
    REP(i, l) {
      addEdge(g, SOURCE(), IN(i), 0);
      addEdge(g, OUT(i), DEST(), 0);
      addEdge(g, IN(i), OUT(i), -1);
      REP(j, l) {
        if (i == j) {
          continue;
        }
        if (ontime[j] + matrix[point[j]][point[i]] <= ontime[i]) {
          addEdge(g, OUT(j), IN(i), 0);
        }
      }
    }
    printf("%d\\n", MinCostFlow(g, SOURCE(), DEST(), l));
  }
}