#include <bits/stdc++.h>
using namespace std;
int read_it() {
  string s;
  cin >> s;
  if (s == "?") {
    return -1;
  } else {
    return atoi(s.c_str());
  }
}
int pop(vector<int>& v) {
  int x = v.back();
  v.pop_back();
  return x;
}
int n;
int source, dest, fre, required, nodes;
int C[2 * 310][2 * 310], F[2 * 310][2 * 310], from[2 * 310];
vector<int> G[2 * 310];
bool viz[2 * 310];
vector<int> no_cycle[310], all_fre;
int pr[310];
class Cycle {
  int dim, max_level;
  vector<int> level[310], fre;
  bool empty() { return max_level == -1; }

 public:
  Cycle() : max_level(-1) {}
  Cycle(int dim) : dim(dim), max_level(-1) {}
  void add(int lvl, int i) {
    level[lvl].push_back(i);
    max_level = max(max_level, lvl);
  }
  void add_fre(int i) {
    fre.push_back(i);
    max_level = max(max_level, 0);
  }
  void pop(int lvl) {
    level[lvl].pop_back();
    int new_max_level = -1;
    for (int i = 0; i <= max_level; ++i) {
      if (!level[i].empty()) new_max_level = i;
    }
    if (!fre.empty()) {
      new_max_level = max(new_max_level, 0);
    }
    max_level = new_max_level;
  }
  int level_needs(int i) {
    if (empty()) return 0;
    if (i == 0) {
      if (level[0].empty()) return dim;
      int val = dim - (level[0].size() % dim);
      return val == dim ? 0 : val;
    } else {
      if (i > max_level) return 0;
      return (level[i].empty() ? 1 : 0);
    }
  }
  int needs() {
    if (empty()) return 0;
    int needs = 0;
    for (int i = 0; i <= max_level; ++i) {
      needs += level_needs(i);
    }
    needs -= fre.size();
    needs = max(needs, 0);
    return needs;
  }
  void wire() {
    if (empty()) return;
    for (int i = 0; i <= max_level; ++i) {
      while (level_needs(i)) {
        add(i, ::pop(fre));
      }
    }
    while (!fre.empty()) {
      add(1, ::pop(fre));
    }
    for (int i = 0; i < level[0].size(); i += dim) {
      for (int j = 0; j < dim; ++j) {
        int jj = (j + 1 == dim ? 0 : j + 1);
        pr[level[0][i + j]] = level[0][i + jj];
      }
    }
    for (int i = 1; i <= max_level; ++i) {
      for (auto el : level[i]) {
        pr[el] = level[i - 1][0];
      }
    }
  }
  void print() {
    cout << "Cycle " << dim << ":\n";
    for (int i = 0; i <= max_level; ++i) {
      cout << "Level " << i << ": " << level[i].size() << "\n";
    }
    cout << "Free " << fre.size() << "\n";
  }
} cycle[310];
string name(int x) {
  char s[30];
  if (x == source) {
    return "Source";
  } else if (x == dest) {
    return "Dest";
  } else if (x == fre) {
    return "All Free";
  } else if (x > n) {
    return "Cycle " + to_string(x - n);
  } else {
    return "Free " + to_string(x - 1);
  }
}
void add_edge(int x, int y, int c) {
  G[x].push_back(y);
  G[y].push_back(x);
  C[x][y] += c;
}
void build_graph() {
  source = (2 * n) + 1;
  dest = source + 1;
  fre = dest + 1;
  nodes = fre;
  for (int i = 1; i <= nodes; ++i) {
    G[i].clear();
    for (int j = 1; j <= nodes; ++j) {
      C[i][j] = F[i][j] = 0;
    }
  }
  for (int f = 0; f < n; ++f) {
    add_edge(source, f + 1, no_cycle[f].size());
  }
  for (int f = 0; f < n; ++f) {
    for (int c = 1; c <= n; ++c) {
      if (cycle[c].level_needs(f)) {
        add_edge(f + 1, c + n, cycle[c].level_needs(f));
      }
    }
  }
  add_edge(source, fre, all_fre.size());
  for (int c = 1; c <= n; ++c) {
    add_edge(fre, c + n, all_fre.size());
  }
  required = 0;
  for (int c = 1; c <= n; ++c) {
    add_edge(c + n, dest, cycle[c].needs());
    required += cycle[c].needs();
  }
}
void dfs(int x) {
  viz[x] = true;
  for (auto y : G[x]) {
    if (!viz[y] && F[x][y] != C[x][y]) {
      from[y] = x;
      dfs(y);
    }
  }
}
bool find_path() {
  for (int i = 1; i <= nodes; ++i) {
    from[i] = viz[i] = 0;
  }
  dfs(source);
  return viz[dest];
}
int max_flow() {
  int flow = 0;
  while (find_path()) {
    int minf = 1e9;
    for (int i = dest; i != source; i = from[i]) {
      minf = min(minf, C[from[i]][i] - F[from[i]][i]);
    }
    flow += minf;
    for (int i = dest; i != source; i = from[i]) {
      F[from[i]][i] += minf;
      F[i][from[i]] -= minf;
    }
  }
  return flow;
}
int main() {
  cin >> n;
  int no_cycle_max = -1;
  for (int i = 1; i <= n; ++i) {
    cycle[i] = Cycle(i);
  }
  for (int i = 1; i <= n; ++i) {
    int x, y;
    x = read_it();
    y = read_it();
    if (x != -1 && y != -1) {
      cycle[y].add(x, i);
    } else if (y != -1) {
      cycle[y].add_fre(i);
    } else if (x != -1) {
      no_cycle[x].push_back(i);
      no_cycle_max = max(no_cycle_max, x);
    } else {
      all_fre.push_back(i);
    }
  }
  int repr_max = (no_cycle_max != -1 ? pop(no_cycle[no_cycle_max]) : -1);
  int keeper_of_max = 1;
  bool found = false;
  for (int i = 1; i <= n; ++i) {
    if (repr_max != -1) cycle[i].add(no_cycle_max, repr_max);
    build_graph();
    int f = max_flow();
    if (f == required) {
      found = true;
      keeper_of_max = i;
      break;
    }
    if (repr_max != -1) cycle[i].pop(no_cycle_max);
  }
  if (!found) {
    cout << "-1\n";
    return 0;
  }
  for (int f = 0; f < n; ++f) {
    for (int c = 1; c <= n; ++c) {
      while (F[f + 1][c + n]) {
        cycle[c].add(f, pop(no_cycle[f]));
        --F[f + 1][c + n];
      }
    }
    while (!no_cycle[f].empty()) {
      if (f != 0)
        cycle[keeper_of_max].add(f, pop(no_cycle[f]));
      else
        cycle[1].add(f, pop(no_cycle[f]));
    }
  }
  for (int c = 1; c <= n; ++c) {
    while (F[fre][c + n]) {
      cycle[c].add_fre(pop(all_fre));
      --F[fre][c + n];
    }
  }
  while (!all_fre.empty()) {
    cycle[1].add_fre(pop(all_fre));
  }
  for (int i = 1; i <= n; ++i) {
    cycle[i].wire();
  }
  for (int i = 1; i <= n; ++i) {
    cout << pr[i] << " ";
  }
}
