#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());
template <class T = int>
T __rand(T range = numeric_limits<T>::max()) {
  return (T)(rng() % range);
}
template <class T>
ostream& operator,(ostream& out, const T& thing) {
  return out << ", " << thing;
}
template <class U, class V>
ostream& operator<<(ostream& out, const pair<U, V>& p) {
  return (out << "(" << p.first, p.second) << ")";
}
template <class A, class B>
ostream& operator<<(ostream& out, const tuple<A, B>& t) {
  return (out << "(" << get<0>(t), get<1>(t)) << ")";
}
template <class A, class B, class C>
ostream& operator<<(ostream& out, const tuple<A, B, C>& t) {
  return (out << "(" << get<0>(t), get<1>(t), get<2>(t)) << ")";
}
template <class T>
ostream& operator<<(ostream& out, const vector<T>& container) {
  out << "{";
  if (((int)container.size())) out << container[0];
  for (int i = 0; i++ < ((int)container.size()) - 1;) out, container[i];
  return out << "}";
}
template <class x>
vector<typename x::value_type> $v(const x& a) {
  return vector<typename x::value_type>(a.begin(), a.end());
}
template <class u>
vector<typename iterator_traits<u>::value_type> $v(u a, u b) {
  return vector<typename iterator_traits<u>::value_type>(a, b);
}
const int maxk = 20;
const int maxn = 501010;
bool removed[maxn];
struct edge {
  int id;
  int v;
  edge(int id_, int v_) : id(id_), v(v_) {}
  bool is_removed() { return removed[id]; }
  void set_remove() { removed[id] = true; }
};
ostream& operator<<(ostream& out, const edge& u) {
  return out << "edge(" << u.id << ", " << u.v << ")";
}
list<edge> euler_cycle(vector<vector<edge>>& gr, int u) {
  list<edge> ans;
  while (true) {
    ;
    while (((int)gr[u].size()) and gr[u].back().is_removed()) gr[u].pop_back();
    if (!((int)gr[u].size())) break;
    gr[u].back().set_remove();
    ans.push_back(gr[u].back());
    u = gr[u].back().v;
  }
  for (auto it = ans.begin(); it != ans.end();) {
    u = it->v;
    ++it;
    ans.splice(it, euler_cycle(gr, u));
  }
  return ans;
}
int n;
pair<int, int> edges[maxn];
bool is_connected(const vector<vector<edge>>& gr) {
  int cnt_single = 0;
  for (int i = -1; ++i < ((int)gr.size());)
    cnt_single += ((int)gr[i].size()) == 0;
  vector<bool> visited(((int)gr.size()));
  int start = 0;
  while (((int)gr[start].size()) == 0) ++start;
  visited[start] = true;
  int cnt_vis = 1;
  queue<int> qu;
  for (qu.push(start); qu.size(); qu.pop()) {
    int u = qu.front();
    for (auto it : gr[u]) {
      int v = it.v;
      if (visited[v]) continue;
      visited[v] = true;
      ++cnt_vis;
      qu.push(v);
    }
  }
  return cnt_vis == ((int)gr.size()) - cnt_single;
}
int main(void) {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n;
  for (int i = -1; ++i < n;) cin >> edges[i].first >> edges[i].second;
  int ans = 0;
  vector<vector<edge>> gr, prev_gr;
  for (int k = 0; k <= maxk; ++k) {
    ;
    prev_gr = gr;
    gr.clear();
    ;
    int mask = (1 << k) - 1;
    gr.resize(mask + 1);
    for (int i = -1; ++i < n;) {
      int u = edges[i].first & mask;
      int v = edges[i].second & mask;
      gr[u].emplace_back(i, v);
      gr[v].emplace_back(i, u);
    };
    if (!is_connected(gr)) break;
    if (0) cerr << "connected " << endl;
    bool has_odd_node = false;
    for (int i = -1; ++i < ((int)gr.size());)
      if (((int)gr[i].size()) & 1) {
        has_odd_node = true;
        break;
      };
    if (has_odd_node) break;
    ans = k;
  };
  cout << ans << '\n';
  int start = 0;
  ;
  while (((int)prev_gr[start].size()) == 0) ++start;
  ;
  int mask = (1 << ans) - 1;
  for (auto i : euler_cycle(prev_gr, start)) {
    int tail = i.v;
    int u = 2 * i.id + 1;
    int v = 2 * i.id + 2;
    if ((edges[i.id].first & mask) == tail) swap(u, v);
    cout << u << ' ' << v << ' ';
  }
  return 0;
}
