#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 5, INF = 1e9;
int first[MAX_N], d[MAX_N], q[MAX_N], p[MAX_N], len[MAX_N], wasLen[MAX_N],
    cnt[MAX_N], nxt[MAX_N], needForLen[MAX_N];
vector<int> g[MAX_N];
set<pair<int, int> > needed;
map<pair<int, int>, vector<int> > ans;
char s[MAX_N];
int getNum(char *s) {
  if (s[0] == '?') return -1;
  return atoi(s);
}
struct Edge {
  int v, u, c, f;
  Edge() {}
  Edge(int v, int u, int c, int f) : v(v), u(u), c(c), f(f) {}
};
vector<Edge> edges;
void addEdge(int v, int u, int c) {
  g[v].push_back((int)((edges).size()));
  edges.push_back(Edge(v, u, c, 0));
  g[u].push_back((int)((edges).size()));
  edges.push_back(Edge(u, v, 0, 0));
}
void addFlow(int e, int f) {
  edges[e].f += f;
  edges[e ^ 1].f -= f;
}
int dfs(int v, int t, int can, int curPush) {
  if (v == t) return can;
  int sum = 0;
  for (; first[v] < (int)((g[v]).size()); first[v]++) {
    auto &e = edges[g[v][first[v]]];
    if (d[e.u] != d[v] + 1 || e.c - e.f < curPush) continue;
    int flow = dfs(e.u, t, min(can, e.c - e.f), curPush);
    addFlow(g[v][first[v]], flow);
    can -= flow, sum += flow;
    if (can == 0) return sum;
  }
  return sum;
}
int bfs(int n, int s, int t, int curPush) {
  for (int i = 0; (i) < (n); ++i) d[i] = INF, first[i] = 0;
  int head = 0, tail = 0;
  d[s] = 0;
  q[tail++] = s;
  while (tail > head) {
    int v = q[head++];
    for (int edge : g[v]) {
      auto &e = edges[edge];
      if (e.c >= e.f + curPush && d[e.u] > d[v] + 1)
        d[e.u] = d[v] + 1, q[tail++] = e.u;
    }
  }
  return d[t] != INF;
}
int dinic(int n, int s, int t) {
  int ansFlow = 0;
  while (bfs(n, s, t, 1)) ansFlow += dfs(s, t, INF, 1);
  return ansFlow;
}
int main() {
  int n;
  scanf("%d", &n);
  int maxPreCycle = -1, maxInd = -1;
  for (int i = 0; (i) < (n); ++i) {
    scanf("%s", s);
    p[i] = getNum(s);
    scanf("%s", s);
    len[i] = getNum(s);
    if (len[i] != -1) {
      wasLen[len[i]] = 1;
      if (p[i] == 0) cnt[len[i]]++;
    } else if (maxPreCycle < p[i])
      maxPreCycle = p[i], maxInd = i;
  }
  for (int i = (1); (i) < (n + 1); ++i) {
    bool toChange = 0;
    if (maxInd != -1) {
      len[maxInd] = i;
      if (p[maxInd] == 0) cnt[i]++;
      if (!wasLen[i]) wasLen[i] = 1, toChange = 1;
    }
    for (int j = (1); (j) < (n + 1); ++j) {
      needForLen[j] = 0;
      if (wasLen[j]) {
        needForLen[j] = (j - (cnt[j]) % j) % j;
        if (cnt[j] == 0) needForLen[j] = j;
      }
    }
    needed.clear();
    for (int j = 0; (j) < (n); ++j)
      if (p[j] > 0 && len[j] != -1) {
        for (int g = (1); (g) < (p[j]); ++g)
          needed.insert(make_pair(g, len[j]));
      }
    for (int j = 0; (j) < (n); ++j) {
      if (p[j] > 0 && len[j] != -1) needed.erase(make_pair(p[j], len[j]));
    }
    edges.clear();
    for (int j = 0; (j) < (2 * n + 2 + (int)((needed).size())); ++j)
      g[j].clear();
    int s = 0;
    for (int j = 0; (j) < (n); ++j) addEdge(s, j + 1, 1);
    int curV = n + 1;
    int t = curV + n + (int)((needed).size());
    int needFlow = 0;
    for (int j = (1); (j) < (n + 1); ++j) {
      for (int g = 0; (g) < (n); ++g)
        if ((p[g] == -1 && len[g] == -1) || (p[g] == -1 && len[g] == j) ||
            (p[g] == 0 && len[g] == -1))
          addEdge(g + 1, curV, 1);
      addEdge(curV++, t, needForLen[j]), needFlow += needForLen[j];
    }
    for (auto np : needed) {
      for (int g = 0; (g) < (n); ++g)
        if ((p[g] == -1 && len[g] == -1) ||
            (p[g] == -1 && len[g] == np.second) ||
            (p[g] == np.first && len[g] == -1))
          addEdge(g + 1, curV, 1);
      addEdge(curV++, t, 1), needFlow++;
    }
    int flow = dinic(t + 1, s, t);
    if (needFlow == flow) {
      curV = n + 1;
      for (int j = (1); (j) < (n + 1); ++j) {
        for (int edge : g[curV]) {
          auto &e = edges[edge];
          if (e.f < 0) p[e.u - 1] = 0, len[e.u - 1] = j;
        }
        curV++;
      }
      for (auto np : needed) {
        for (int edge : g[curV]) {
          auto &e = edges[edge];
          if (e.f < 0) p[e.u - 1] = np.first, len[e.u - 1] = np.second;
        }
        curV++;
      }
      for (int j = 0; (j) < (n); ++j) {
        if (p[j] == -1 && len[j] == -1) {
          p[j] = 0, len[j] = 1;
        } else {
          if (p[j] == -1)
            p[j] = 1;
          else if (len[j] == -1) {
            if (p[j] == 0)
              len[j] = 1;
            else
              len[j] = i;
          }
        }
        ans[make_pair(p[j], len[j])].push_back(j);
      }
      for (auto it : ans) {
        auto np = it.first;
        auto v = it.second;
        if (np.first != 0)
          for (int j : v) nxt[j] = ans[make_pair(np.first - 1, np.second)][0];
        else {
          assert((int)((v).size()) % np.second == 0);
          for (int j = 0; j < (int)((v).size()); j += np.second) {
            for (int g = (j); (g) < (j + np.second - 1); ++g)
              nxt[v[g]] = v[g + 1];
            nxt[v[j + np.second - 1]] = v[j];
          }
        }
      }
      for (int i = 0; (i) < (n); ++i) printf("%d ", nxt[i] + 1);
      return 0;
    }
    if (maxInd != -1) {
      len[maxInd] = -1;
      if (p[maxInd] == 0) cnt[i]--;
      if (toChange) wasLen[i] = 0;
    }
  }
  puts("-1");
  return 0;
}
