#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
const int SIZE = 1e6 + 10;
using namespace std;
struct E {
  int k, c;
  E() {}
  E(int _k, int _c) : k(_k), c(_c) {}
} es[4200010];
struct Flow {
  int n, m, dis[500010];
  int qq[500010], qr, ql;
  vector<int> e[500010];
  void init(int _n) {
    n = _n;
    m = 0;
    for (int i = 0; i < n; i++) e[i] = vector<int>();
  }
  void add_edge(int a, int b, int c) {
    e[a].push_back(m);
    es[m] = E(b, c);
    m++;
    e[b].push_back(m);
    es[m] = E(a, 0);
    m++;
  }
  bool BFS() {
    memset(dis, -1, n * sizeof(int));
    ql = qr = 0;
    qq[qr++] = 0;
    dis[0] = 0;
    while (ql != qr && dis[n - 1] == -1) {
      int p = qq[ql++];
      for (__typeof((e[p]).begin()) it = (e[p]).begin(); it != (e[p]).end();
           it++) {
        E ee = es[*it];
        if (ee.c == 0 || dis[ee.k] != -1) continue;
        dis[ee.k] = dis[p] + 1;
        qq[qr++] = ee.k;
      }
    }
    return dis[n - 1] != -1;
  }
  long long go(int p, long long c) {
    if (p == n - 1) return c;
    long long ret = 0, tmp;
    for (__typeof((e[p]).begin()) it = (e[p]).begin(); it != (e[p]).end();
         it++) {
      E &ee = es[*it];
      if (ee.c == 0 || dis[p] + 1 != dis[ee.k]) continue;
      tmp = go(ee.k, min(c - ret, (long long)ee.c));
      ret += tmp;
      ee.c -= tmp;
      es[(*it) ^ 1].c += tmp;
      if (ret == c) break;
    }
    if (ret == 0) dis[p] = -1;
    return ret;
  }
  long long maxflow() {
    long long ret = 0;
    while (BFS()) ret += go(0, 1LL << 60);
    return ret;
  }
} flow;
vector<int> cc[301][301], cn[301];
int need_id, an[301], xx[301], yy[301];
pair<int, int> need[1000001];
int to[301];
bool used[301];
bool match(pair<int, int> X, pair<int, int> Y) {
  if (X.first != Y.first && Y.first != -1) return 0;
  if (X.second != Y.second && Y.second != -1) return 0;
  return 1;
}
void go(int ma_id, int ma_hi, int n) {
  if (ma_id != 1 && ((int)(cc[ma_id][0]).size()) == 0) return;
  vector<pair<int, int> > qq;
  int oo = need_id;
  for (int i = ma_hi; i >= 0; i--) {
    if (((int)(cc[ma_id][i]).size()) == 0) {
      need[++need_id] = make_pair(ma_id, i);
      cc[ma_id][i].push_back(-need_id);
      qq.push_back(make_pair(ma_id, i));
    }
  }
  if (need_id > n) {
    for (int i = 0; i < (((int)(qq).size())); ++i)
      cc[qq[i].first][qq[i].second].pop_back();
    need_id = oo;
    return;
  }
  flow.init(need_id + n + 2);
  for (int i = (1); i < (n + 1); ++i)
    flow.add_edge(need_id + i, need_id + n + 1, 1);
  for (int i = (1); i < (need_id + 1); ++i) {
    flow.add_edge(0, i, 1);
    for (int j = (1); j < (n + 1); ++j) {
      if (used[j]) continue;
      if (match(need[i], make_pair(yy[j], xx[j])))
        flow.add_edge(i, need_id + j, 1);
    }
  }
  if (flow.maxflow() != need_id) {
    need_id = oo;
    return;
  }
  for (int i = 0; i < flow.m; i += 2) {
    if (es[i].k > need_id && es[i + 1].k <= need_id && es[i].c == 0) {
      used[es[i].k - need_id] = 1;
      to[es[i + 1].k] = es[i].k - need_id;
    }
  }
  for (int i = (1); i < (n + 1); ++i) {
    for (int j = 0; j < (n); ++j) {
      for (int k = 0; k < (((int)(cc[i][j]).size())); ++k) {
        if (cc[i][j][k] < 0) cc[i][j][k] = to[-cc[i][j][k]];
      }
    }
  }
  for (int i = (1); i < (n + 1); ++i) {
    if (!used[i]) {
      used[i] = 1;
      if (xx[i] == -1 && yy[i] == -1)
        cc[1][0].push_back(i);
      else if (yy[i] != -1)
        cc[yy[i]][1].push_back(i);
      else if (xx[i] != -1) {
        if (xx[i] == 0)
          cc[1][0].push_back(i);
        else
          cc[ma_id][xx[i]].push_back(i);
      }
    }
  }
  for (int i = (1); i < (n + 1); ++i) {
    for (int j = 0; j < (((int)(cc[i][0]).size())); ++j) {
      if (j % i == 0)
        an[cc[i][0][j]] = cc[i][0][j + i - 1];
      else
        an[cc[i][0][j]] = cc[i][0][j - 1];
    }
    for (int j = (1); j < (n); ++j) {
      for (int k = 0; k < (((int)(cc[i][j]).size())); ++k)
        an[cc[i][j][k]] = cc[i][j - 1][0];
    }
  }
  for (int i = (1); i < (n + 1); ++i) printf("%d%c", an[i], " \n"[i == n]);
  exit(0);
}
int main() {
  int(n);
  scanf("%d", &n);
  int ma_hi = -1;
  for (int i = (1); i < (n + 1); ++i) {
    char s1[20], s2[20];
    scanf("%s", (s1));
    scanf("%s", (s2));
    int x = -1, y = -1;
    if (s1[0] != '?') x = atoi(s1);
    if (s2[0] != '?') y = atoi(s2);
    if (x != -1 && y != -1) {
      cc[y][x].push_back(i);
      used[i] = 1;
    } else if (y != -1)
      cn[y].push_back(i);
    xx[i] = x;
    yy[i] = y;
    ma_hi = max(ma_hi, x);
  }
  int mi = 10000, ma_id = 1;
  for (int i = (1); i < (n + 1); ++i) {
    int hi = n - 1;
    while (hi >= 0 && ((int)(cc[i][hi]).size()) == 0) hi--;
    while (hi >= 0) {
      if (!((int)(cc[i][hi]).size())) {
        need[++need_id] = make_pair(i, hi);
        cc[i][hi].push_back(-need_id);
      }
      hi--;
    }
    if (((int)(cn[i]).size()) && ((int)(cc[i][0]).size()) == 0) {
      need[++need_id] = make_pair(i, 0);
      cc[i][0].push_back(-need_id);
    }
    while (((int)(cc[i][0]).size()) % i) {
      need[++need_id] = make_pair(i, 0);
      cc[i][0].push_back(-need_id);
    }
  }
  for (int ker = 1; ker <= n; ker++) {
    go(ker, ma_hi, n);
  }
  return 0 * puts("-1");
}
