#include <bits/stdc++.h>
using namespace std;
mt19937 rnd;
struct DSU {
  static const int N = (1 << 20) + 10;
  int Parent[N], Rank[N], cnt;
  void init(const int& n) {
    for (int i = 1; i <= n; i++) {
      Parent[i] = i, Rank[i] = 0;
    }
    cnt = n;
  }
  int find(const int& v) {
    if (Parent[v] == v)
      return v;
    else
      return Parent[v] = find(Parent[v]);
  }
  void unite(const int& u, const int& v) {
    int U = find(u), V = find(v);
    if (U == V) return;
    if (Rank[U] < Rank[V]) swap(U, V);
    if (Rank[V] == Rank[U]) Rank[U]++;
    Parent[V] = U, cnt--;
  }
} dsu;
const int B = 20;
const int N = (1 << B) + 10;
int a[N], b[N], deg[N];
int revMask(int mask) {
  int res = 0;
  for (int i = 0; i < B; i++) {
    if (mask & (1 << i)) {
      res |= (1 << (B - 1 - i));
    }
  }
  return res;
}
void init(int k) {
  for (int i = 0; i < (1 << k); i++) {
    deg[i] = 0;
  }
  dsu.init((1 << k));
}
bool check(int k) {
  bool ok = 1;
  set<int> roots;
  for (int i = 0; i < (1 << k) && ok; i++) {
    if (deg[i] & 1) {
      ok = 0;
    } else if (deg[i]) {
      roots.insert(dsu.find(i + 1));
    }
  }
  return ok && roots.size() == 1;
}
vector<multiset<int>> g;
vector<int> path;
void dfs(int v) {
  while (!g[v].empty()) {
    int to = *g[v].rbegin();
    g[v].erase(g[v].find(to));
    g[to].erase(g[to].find(v));
    dfs(to);
  }
  path.push_back(v);
}
void Euler_path(int n) {
  for (int i = 0; i < n; i++) {
    if (deg[i]) {
      dfs(i);
      break;
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n;
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i] >> b[i];
    a[i] = revMask(a[i]);
    b[i] = revMask(b[i]);
  }
  int res = -1, len = 1;
  for (int k = B; k >= 0; k--, len <<= 1) {
    init(k);
    for (int i = 1; i <= n; i++) {
      deg[a[i] / len]++;
      deg[b[i] / len]++;
      dsu.unite(a[i] / len + 1, b[i] / len + 1);
    }
    if (check(k)) {
      res = k;
      break;
    }
  }
  set<pair<pair<int, int>, int>> s;
  g.resize((1 << res));
  for (int i = 1; i <= n; i++) {
    g[a[i] / len].insert(b[i] / len);
    g[b[i] / len].insert(a[i] / len);
    s.insert({{a[i] / len, b[i] / len}, i});
  }
  Euler_path((1 << res));
  cout << res << "\n";
  for (int i = 0; i < path.size() - 1; i++) {
    auto itr = s.lower_bound({{path[i], path[i + 1]}, 0});
    if (itr != s.end() && itr->first.first == path[i] &&
        itr->first.second == path[i + 1]) {
      int id = itr->second;
      cout << 2 * id - 1 << " " << 2 * id << " ";
      s.erase(itr);
      continue;
    }
    itr = s.lower_bound({{path[i + 1], path[i]}, 0});
    if (itr != s.end() && itr->first.first == path[i + 1] &&
        itr->first.second == path[i]) {
      int id = itr->second;
      s.erase(itr);
      cout << 2 * id << " " << 2 * id - 1 << " ";
    }
  }
  return 0;
}
