#include <bits/stdc++.h>
template <typename T>
class IntegerIterator {
 public:
  using value_type = T;
  using difference_type = std::ptrdiff_t;
  using pointer = T*;
  using reference = T;
  using iterator_category = std::input_iterator_tag;
  explicit IntegerIterator(T value) : value(value) {}
  IntegerIterator& operator++() {
    ++value;
    return *this;
  }
  IntegerIterator operator++(int) {
    IntegerIterator copy = *this;
    ++value;
    return copy;
  }
  IntegerIterator& operator--() {
    --value;
    return *this;
  }
  IntegerIterator operator--(int) {
    IntegerIterator copy = *this;
    --value;
    return copy;
  }
  T operator*() const { return value; }
  bool operator==(IntegerIterator rhs) const { return value == rhs.value; }
  bool operator!=(IntegerIterator rhs) const { return !(*this == rhs); }

 private:
  T value;
};
template <typename T>
class IntegerRange {
 public:
  IntegerRange(T begin, T end) : begin_(begin), end_(end) { ; }
  IntegerIterator<T> begin() const { return IntegerIterator<T>(begin_); }
  IntegerIterator<T> end() const { return IntegerIterator<T>(end_); }

 private:
  T begin_;
  T end_;
};
template <typename T>
class ReversedIntegerRange {
  using IteratorType = std::reverse_iterator<IntegerIterator<T>>;

 public:
  ReversedIntegerRange(T begin, T end) : begin_(begin), end_(end) { ; }
  IteratorType begin() const {
    return IteratorType(IntegerIterator<T>(begin_));
  }
  IteratorType end() const { return IteratorType(IntegerIterator<T>(end_)); }

 private:
  T begin_;
  T end_;
};
template <typename T>
IntegerRange<T> range(T to) {
  return IntegerRange<T>(0, to);
}
template <typename T>
IntegerRange<T> range(T from, T to) {
  return IntegerRange<T>(from, to);
}
template <typename T>
IntegerRange<T> inclusiveRange(T to) {
  return IntegerRange<T>(0, to + 1);
}
template <typename T>
IntegerRange<T> inclusiveRange(T from, T to) {
  return IntegerRange<T>(from, to + 1);
}
template <typename T>
ReversedIntegerRange<T> downrange(T from) {
  return ReversedIntegerRange<T>(from, 0);
}
template <typename T>
ReversedIntegerRange<T> downrange(T from, T to) {
  return ReversedIntegerRange<T>(from, to);
}
template <typename T>
ReversedIntegerRange<T> inclusiveDownrange(T from) {
  return ReversedIntegerRange<T>(from + 1, 0);
}
template <typename T>
ReversedIntegerRange<T> inclusiveDownrange(T from, T to) {
  return ReversedIntegerRange<T>(from + 1, to);
}
class DSU {
 public:
  explicit DSU(std::size_t n) : dsu(n) {
    for (std::size_t i = 0; i < n; ++i) {
      dsu[i] = i;
    }
  }
  std::size_t getSet(std::size_t v) {
    ;
    if (v == dsu[v]) {
      return v;
    }
    return dsu[v] = getSet(dsu[v]);
  }
  bool unite(std::size_t u, std::size_t v) {
    ;
    ;
    u = getSet(u);
    v = getSet(v);
    if (u == v) {
      return false;
    } else {
      dsu[v] = u;
      return true;
    }
  }
  std::size_t components() const {
    std::size_t count = 0;
    for (std::size_t i = 0; i < dsu.size(); ++i) {
      if (dsu[i] == i) {
        ++count;
      }
    }
    return count;
  }

 private:
  std::vector<std::size_t> dsu;
};
using namespace std;
class CDzhonniIOzhereleMegan {
 public:
  static constexpr int kStressCount = 0;
  static void generateTest(std::ostream& test) {}
  void solve(std::istream& in, std::ostream& out) {
    int n;
    in >> n;
    vector<int> a(2 * n);
    for (int i : range(2 * n)) {
      in >> a[i];
    }
    for (int k : inclusiveDownrange(20, 0)) {
      vector<int> degs(1 << k);
      for (int i : range(2 * n)) {
        ++degs[a[i] % (1 << k)];
      }
      bool ok = true;
      for (int i : range(1 << k)) {
        if (degs[i] % 2 != 0) {
          ok = false;
          break;
        }
      }
      if (!ok) {
        continue;
      }
      DSU dsu(1 << k);
      for (int i : range(n)) {
        dsu.unite(a[2 * i] % (1 << k), a[2 * i + 1] % (1 << k));
      }
      int expected_components = 1;
      for (int x : degs) {
        if (x == 0) {
          ++expected_components;
        }
      }
      if (dsu.components() != expected_components) {
        continue;
      }
      out << k << "\n";
      vector<set<int>> edges(1 << k);
      for (int i : range(0, n)) {
        edges[a[2 * i] % (1 << k)].insert(2 * i);
        edges[a[2 * i + 1] % (1 << k)].insert(2 * i + 1);
      }
      int v = a[0] % (1 << k);
      stack<int> s;
      stack<int> s2;
      s.push(v);
      s2.push(-1);
      vector<int> ans;
      while (!s.empty()) {
        auto w = s.top();
        if (!edges[w].empty()) {
          auto e = *edges[w].begin();
          auto u = a[e ^ 1] % (1 << k);
          edges[w].erase(e);
          edges[u].erase(e ^ 1);
          s.push(u);
          s2.push(e ^ 1);
        } else {
          ans.push_back(w);
          s.pop();
          s2.pop();
        }
      }
      map<pair<int, int>, set<int>> pdr;
      for (int i : range(0, n)) {
        pdr[{
                a[2 * i] % (1 << k),
                a[2 * i + 1] % (1 << k),
            }]
            .insert(2 * i);
        pdr[{
                a[2 * i + 1] % (1 << k),
                a[2 * i] % (1 << k),
            }]
            .insert(2 * i + 1);
      }
      for (int i = 0; i + 1 < ans.size(); ++i) {
        assert(!pdr.at({ans[i], ans[i + 1]}).empty());
        auto z = *pdr.at({ans[i], ans[i + 1]}).begin();
        out << z + 1 << ' ' << (z ^ 1) + 1 << " ";
        pdr[{ans[i], ans[i + 1]}].erase(z);
        pdr[{ans[i + 1], ans[i]}].erase(z ^ 1);
      }
      return;
    }
  }
};
int main() {
  std::ios_base::sync_with_stdio(false);
  CDzhonniIOzhereleMegan solver;
  std::istream& in(std::cin);
  std::ostream& out(std::cout);
  in.tie(nullptr);
  out << std::fixed;
  out.precision(20);
  solver.solve(in, out);
  return 0;
}
