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

#include <stdio.h>
#include <string.h>
#define MaxN 110

const int oo = 0x7fffffff;
int g[MaxN][MaxN], d[MaxN];
bool used[MaxN], vst[MaxN];

int main() {
  int min, n, m, max, tmp, pre, cur, a, b, w, cnt;

  while (scanf("%d%d", &n, &m), n) {
    min = oo, cnt = 0;
    memset(g, 0, sizeof(g));
    memset(used, 0, sizeof(used));
    int Res = 0;
    for (int i = 0; i < m; ++i) {
      scanf("%d%d%d", &a, &b, &w);
      if (w < 0) {
        Res += w;
        continue;
      }
      g[a][b] += w;
      g[b][a] = g[a][b];
    }
    if (n < 2) {
      printf("%d\\n", Res);
      continue;
    }
    for (int i = 1; i < n; ++i) {
      memset(vst, 0, sizeof(vst));
      vst[0] = 1;
      cur = pre = d[0] = 0;
      for (int k = 1; k < n; ++k)
        d[k] = g[0][k];
      for (int j = i; j < n; ++j) {
        max = 0;
        pre = cur;
        for (int k = 0; k < n; ++k) {
          if (vst[k] || used[k])
            continue;
          if (d[k] > max) {
            max = d[k];
            cur = k;
          }
        }
        vst[cur] = 1;
        for (int k = 0; k < n; ++k) {
          if (vst[k] || used[k])
            continue;
          d[k] += g[cur][k];
        }
      }
      used[cur] = 1;
      for (int j = 0; j < n; ++j) {
        if (j == pre || used[j])
          continue;
        g[pre][j] += g[cur][j];
        g[j][pre] = g[pre][j];
      }
      tmp = 0;
      for (int j = 0; j < n; ++j) {
        if (used[j])
          continue;
        tmp += g[cur][j];
      }
      if (tmp < min)
        min = tmp;
      else
        continue;
    }
    printf("%d\\n", Res + min);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
typedef long long LL;
const LL oo = 1LL << 60;
const LL B = 1LL << 31; // make negative ones to be positive
const LL W = 10000;     // max number of edges in cut
const int Max = 128;
const int MaxE = 500000;
struct box {
  int to;
  LL f;
  box *s, *r;
} edge[MaxE], *hd[Max], *cur[Max], *cp;
box rem[MaxE];
int n, s, t, vH[Max], H[Max];
box *addEdge(int x, int y, LL f) {
  box *p = cp++, *q = cp++;
  p->to = y, p->s = hd[x], hd[x] = p;
  q->to = x, q->s = hd[y], hd[y] = q;
  p->f = f, q->f = 0;
  p->r = q, q->r = p;
  return p;
}
LL aug(int x, LL f) {
  if (x == t)
    return f;
  LL d;
  int minH = n - 1;
  for (box *p = cur[x]; p; p = p->s)
    if (p->f > 0 && H[x] == H[p->to] + 1) {
      cur[x] = p;
      if ((d = aug(p->to, f < p->f ? f : p->f)) > 0) {
        p->f -= d, p->r->f += d;
        return d;
      }
      if (H[s] >= n)
        return 0;
    }
  if (--vH[H[x]] == 0)
    H[s] = n;
  for (box *p = cur[x] = hd[x]; p; p = p->s)
    if (p->f > 0 && H[p->to] < minH)
      minH = H[p->to];
  ++vH[H[x] = minH + 1];
  return 0;
}
LL maxFlow() {
  memcpy(cur, hd, sizeof(cur[0]) * n);
  memset(vH, 0, sizeof(vH[0]) * (n + 1));
  memset(H, 0, sizeof(H[0]) * n);
  LL res = 0, d;
  vH[0] = n;
  while (H[s] < n)
    if ((d = aug(s, oo * 2LL)) > 0)
      res += d;
  return res;
}
int color[Max];
int dfs(int x, int s) {
  int sz = 1;
  color[x] = s;
  for (box *p = hd[x]; p; p = p->s)
    if (color[p->to] != s && p->f > 0)
      sz += dfs(p->to, s);
  return sz;
}
LL cal(int N, int cn, int c) {
  if (cn == 1)
    return oo;
  int cs = -1, ct = -1;
  for (int i = 0; i < N && ct == -1; i++)
    if (color[i] == c) {
      if (cs == -1)
        cs = i;
      else if (ct == -1)
        ct = i;
    }
  // printf("%d %d %d => %d %d %d\\n",N,cn,c,N,cs,ct);
  n = N, s = cs, t = ct;
  memcpy(edge, rem, sizeof(rem[0]) * (cp - edge));
  LL cm = maxFlow();
  LL cf = cm / W, cd = cm % W;
  LL cr = cf - cd * B;
  // printf("=> %lld %lld | %lld\\n",cf,cd,cr);
  int ns = dfs(cs, cs);
  // printf("ns = %d\\n",ns);for (int i = 0;i < N;i++)printf("%d
  // ",color[i]);puts("");
  for (int i = 0; i < N; i++)
    if (color[i] == c)
      color[i] = ct;
  cr = min(cr, cal(N, ns, cs));
  cr = min(cr, cal(N, cn - ns, ct));
  return cr;
}
LL mp[Max][Max];
int main() {
  for (int N, M; scanf("%d%d", &N, &M) && N;) {
    for (int i = 0; i < N; i++)
      for (int j = 0; j < N; j++)
        mp[i][j] = oo;
    for (int i = 0; i < M; i++) {
      int x, y, c;
      scanf("%d%d%d", &x, &y, &c);
      if (mp[x][y] == oo)
        mp[x][y] = c;
      else
        mp[x][y] += c;
    }
    memset(hd, 0, sizeof(hd[0]) * N);
    cp = edge;
    for (int i = 0; i < N; i++)
      for (int j = 0; j < N; j++)
        if (mp[i][j] < B)
          addEdge(i, j, (mp[i][j] + B) * W + 1);
    memcpy(rem, edge, sizeof(rem[0]) * (cp - edge));
    memset(color, -1, sizeof(color[0]) * N);
    printf("%lld\\n", cal(N, N, -1));
  }
  return 0;
}