Problem p03811 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define ref(i, x, y) for (int i = x; i <= y; ++i)
const int N = 2001;
int n, m, _m, a[N], A[N], b[N][10], t[N * 10], fa[N * 10];
bool v[N * 10], f[N];
bool pri(int x, int y) { return y ? pri(y, x % y) : (x == 1); }
bool cmp(int x, int y) { return b[x / 10][x % 10] < b[y / 10][y % 10]; }
int ask(int x) { return fa[x] == x ? fa[x] : ask(fa[x]); }
void unite(int x, int y) {
  x = ask(x), y = ask(y);
  if (y != x)
    fa[y] = x;
}
int main() {
  scanf("%d", &n);
  ref(i, 1, n) scanf("%d", &a[i]);
  sort(a + 1, a + n + 1);
  ref(i, 1, n) {
    int S = a[i], s = (int)sqrt(a[i]);
    ref(j, 2, s) if (S % j == 0) {
      while (S % j == 0)
        S /= j;
      b[i][++b[i][0]] = j;
    }
    if (S > 1)
      b[i][++b[i][0]] = S;
    ref(j, 1, b[i][0]) t[++m] = i * 10 + j;
    A[i] = a[i];
    a[i] = i;
  }
  sort(t + 1, t + m + 1, cmp);
  _m = n;
  for (int i = 1, la = -1; i <= m; ++i) {
    int &s = b[t[i] / 10][t[i] % 10];
    _m += (s != la);
    la = s;
    s = _m;
  }
  m = _m;
  ref(i, 1, n) {
    int tot = 0, p = 0, ap = 0;
    ref(j, 1, m) fa[j] = j, v[j] = 0;
    ref(j, i, n) ref(I, 1, b[a[j]][0]) unite(j, b[a[j]][I]);
    ref(j, i, n) if (ask(j) == j) tot++;
    ref(j, i, n) if (!v[ask(j)] && !f[a[j]]) {
      v[ask(j)] = 1, tot--;
      if (tot == 0) {
        p = j;
        break;
      }
    }
    ap = a[p];
    for (int j = p; j > i; --j)
      a[j] = a[j - 1];
    a[i] = ap;
    ref(j, i + 1, n) {
      int x = A[a[i]], y = A[a[j]];
      if (x < y) {
        f[a[j]] = pri(x, y);
      } else {
        f[a[j]] = f[a[j]] && pri(x, y);
      }
    }
  }
  ref(i, 1, n) printf("%d ", A[a[i]]);
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define ref(i, x, y) for (int i = x; i <= y; ++i)
const int N = 2001;
int n, m, _m, a[N], A[N], b[N][10], t[N * 10], fa[N * 10];
bool v[N * 10], f[N];
bool pri(int x, int y) { return y ? pri(y, x % y) : (x == 1); }
bool cmp(int x, int y) { return b[x / 10][x % 10] < b[y / 10][y % 10]; }
int ask(int x) { return fa[x] == x ? x : fa[x] = ask(fa[x]); }
void unite(int x, int y) {
  x = ask(x), y = ask(y);
  if (y != x)
    fa[y] = x;
}
int main() {
  scanf("%d", &n);
  ref(i, 1, n) scanf("%d", &a[i]);
  sort(a + 1, a + n + 1);
  ref(i, 1, n) {
    int S = a[i], s = (int)sqrt(a[i]);
    ref(j, 2, s) if (S % j == 0) {
      while (S % j == 0)
        S /= j;
      b[i][++b[i][0]] = j;
    }
    if (S > 1)
      b[i][++b[i][0]] = S;
    ref(j, 1, b[i][0]) t[++m] = i * 10 + j;
    A[i] = a[i];
    a[i] = i;
  }
  sort(t + 1, t + m + 1, cmp);
  _m = n;
  for (int i = 1, la = -1; i <= m; ++i) {
    int &s = b[t[i] / 10][t[i] % 10];
    _m += (s != la);
    la = s;
    s = _m;
  }
  m = _m;
  ref(i, 1, n) {
    int tot = 0, p = 0, ap = 0;
    ref(j, 1, m) fa[j] = j, v[j] = 0;
    ref(j, i, n) ref(I, 1, b[a[j]][0]) unite(j, b[a[j]][I]);
    ref(j, i, n) if (ask(j) == j) tot++;
    ref(j, i, n) if (!v[ask(j)] && !f[a[j]]) {
      v[ask(j)] = 1, tot--;
      if (tot == 0) {
        p = j;
        break;
      }
    }
    ap = a[p];
    for (int j = p; j > i; --j)
      a[j] = a[j - 1];
    a[i] = ap;
    ref(j, i + 1, n) {
      int x = A[a[i]], y = A[a[j]];
      if (x < y) {
        f[a[j]] = pri(x, y);
      } else {
        f[a[j]] = f[a[j]] && pri(x, y);
      }
    }
  }
  ref(i, 1, n) printf("%d ", A[a[i]]);
}