#include <bits/stdc++.h>
using namespace std;
template <typename T1, typename T2>
inline void chkmin(T1 &first, T2 second) {
  if (first > second) first = second;
}
template <typename T1, typename T2>
inline void chkmax(T1 &first, T2 second) {
  if (first < second) first = second;
}
const string FILENAME = "input";
int n;
map<pair<int, int>, vector<int>> type;
bool vis[301];
int cnt[301];
int max_dist[301];
int maxd = 0;
int s, t, L, R;
vector<pair<pair<int, int>, int>> arr[2];
vector<int> flow;
vector<int> c;
vector<int> edge[1001];
vector<int> to;
void new_edge(int i, int j, int c) {
  edge[i].push_back(flow.size());
  flow.push_back(0);
  edge[j].push_back(flow.size());
  flow.push_back(0);
  ::c.push_back(c);
  ::c.push_back(0);
  to.push_back(j);
  to.push_back(i);
}
int ver = 1;
int used[1001];
int dfs(int i, int f = 1e9) {
  if (used[i] == ver || f == 0) return 0;
  if (i == t) {
    return f;
  }
  used[i] = ver;
  for (int j : edge[i]) {
    int ans = dfs(to[j], min(c[j] - flow[j], f));
    if (ans != 0) {
      flow[j] += ans;
      flow[j ^ 1] -= ans;
      return ans;
    }
  }
  return 0;
}
int ans[301];
vector<int> circle[301];
int last[301][301];
int lastd[301];
void flow_find() {
  L = arr[0].size();
  R = arr[1].size();
  s = L + R;
  t = s + 1;
  vector<pair<pair<int, int>, int>> mod;
  for (int i = 0; i < L; ++i) {
    auto a = arr[0][i].first;
    for (int j = 0; j < R; ++j) {
      auto b = arr[1][j].first;
      if ((a.first == -1 || a.first == b.first) &&
          (a.second == -1 || a.second == b.second)) {
        new_edge(i, j + L, 1e9);
        if (a == b) {
          int f = min(arr[0][i].second, arr[1][j].second);
          mod.push_back({a, f});
          arr[0][i].second -= f;
          arr[1][j].second -= f;
        }
      }
    }
  }
  for (int i = 0; i < L; ++i) {
    new_edge(s, i, arr[0][i].second);
  }
  for (int i = 0; i < R; ++i) {
    new_edge(i + L, t, arr[1][i].second);
  }
  while (dfs(s)) {
    ++ver;
  }
  ++ver;
  for (int i = 0; i < L; ++i) {
    for (auto j : mod) {
      if (arr[0][i].first == j.first) {
        arr[0][i].second += j.second;
        for (int q : edge[i]) {
          if (c[q] == 0) continue;
          if (arr[1][to[q] - L].first == j.first) {
            flow[q] += j.second;
            flow[q ^ 1] -= j.second;
            break;
          }
        }
        break;
      }
    }
  }
  for (int i = 0; i < R; ++i) {
    for (int j : edge[i + L]) {
      if (c[j] - flow[j] > 0 && c[j] != 0) {
        for (int i = 0; i <= t; ++i) edge[i].clear();
        flow.clear();
        c.clear();
        to.clear();
        return;
      }
    }
  }
  for (int i = 0; i < R; ++i) {
    auto a = arr[1][i].first;
    for (int j : edge[i + L]) {
      if (c[j] != 0) continue;
      auto b = arr[0][to[j]].first;
      if (a.first != 0) {
        for (int q = 0; q < -flow[j]; ++q) {
          int id = type[b].back();
          type[b].pop_back();
          ans[id] = last[a.second][a.first - 1];
          last[a.second][a.first] = id;
          lastd[a.first] = id;
        }
      } else {
        for (int q = 0; q < -flow[j]; ++q) {
          circle[a.second].push_back(type[b].back());
          type[b].pop_back();
        }
      }
    }
    if (a.first == 0) {
      for (int j = 0; j < circle[a.second].size(); j += a.second) {
        for (int q = 0; q < a.second; ++q) {
          ans[circle[a.second][j + q]] =
              circle[a.second][j + ((q + 1) % a.second)];
        }
      }
      last[a.second][a.first] = circle[a.second][0];
      lastd[a.first] = circle[a.second][0];
    }
  }
  for (auto i : type) {
    for (int j : i.second) {
      assert(i.first.first != 0 || i.first.second == -1);
      if (i.first == make_pair(-1, -1) || i.first == make_pair(0, -1) ||
          i.first == make_pair(0, 0)) {
        ans[j] = j;
      } else if (i.first.first == -1) {
        ans[j] = last[i.first.second][0];
      } else if (i.first.second == -1) {
        ans[j] = lastd[i.first.first - 1];
      } else {
        ans[j] = last[i.first.second][i.first.first - 1];
      }
    }
  }
  for (int i = 0; i < n; ++i) cout << ans[i] + 1 << ' ';
  cout << endl;
  exit(0);
}
int main(int argc, char const *argv[]) {
  ios::sync_with_stdio(false);
  cin >> n;
  for (int i = 0; i < n; ++i) {
    string s1, s2;
    int a, b;
    cin >> s1 >> s2;
    if (s1 == "?") {
      a = -1;
    } else {
      a = atoi(s1.c_str());
    }
    if (s2 == "?") {
      b = -1;
    } else {
      b = atoi(s2.c_str());
      vis[b] = true;
    }
    if (a == 0 && b != -1) {
      ++cnt[b];
    }
    if (a != -1 && b != -1) {
      chkmax(max_dist[b], a);
    }
    chkmax(maxd, a);
    type[{a, b}].push_back(i);
  }
  for (auto i : type) arr[0].push_back({i.first, i.second.size()});
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j) {
      if (!vis[j] && j != i) continue;
      int need = max(j, ((cnt[j] - 1) / j + 1) * j);
      arr[1].push_back({{0, j}, need});
      if (j != i) {
        for (int k = 1; k <= max_dist[j]; ++k) {
          arr[1].push_back({{k, j}, 1});
        }
      } else {
        for (int k = 1; k <= maxd; ++k) {
          arr[1].push_back({{k, j}, 1});
        }
      }
    }
    if (arr[1].size() <= n) {
      flow_find();
    }
    arr[1].clear();
  }
  cout << -1 << endl;
}
