#include <bits/stdc++.h>
using namespace std;
template <class T>
bool umin(T& a, const T& b) {
  return a > b ? a = b, true : false;
}
template <class T>
bool umax(T& a, const T& b) {
  return a < b ? a = b, true : false;
}
const long long mod = 1e9 + 7;
const long long inf = 1e18;
signed main() {
  auto solve = [&]() -> void {
    long long n;
    cin >> n;
    vector<long long> a(n * 2), mm((1 << 20), 0);
    for (auto& x : a) cin >> x;
    for (long long k = 20; ~k; k--) {
      long long tmp = (1 << k) - 1;
      vector<vector<pair<long long, long long>>> edges(1 << k);
      vector<long long> used(1 << k, 0);
      function<void(long long)> check_dfs = [&](long long u) {
        used[u] = 1;
        for (auto x : edges[u]) {
          if (!used[x.first]) check_dfs(x.first);
        }
      };
      for (long long i = 0; i < 2 * n; i += 2) {
        long long u = (a[i] & tmp), v = (a[i + 1] & tmp);
        edges[u].push_back({v, i});
        edges[v].push_back({u, i | 1});
      }
      check_dfs(a[0] & tmp);
      bool ok = 0;
      for (long long i = 0; i < 2 * n; i++) {
        if (((long long)edges[(a[i] & tmp)].size() & 1) ||
            !used[(a[i] & tmp)]) {
          ok = 1;
          break;
        }
      }
      if (ok) continue;
      cout << k << "\n";
      used.assign(n, 0);
      function<void(long long, long long)> dfs = [&](long long u,
                                                     long long par) {
        while (!edges[u].empty()) {
          auto x = edges[u].back();
          edges[u].pop_back();
          if (used[x.second / 2]) continue;
          used[x.second / 2] = 1;
          dfs(x.first, x.second);
        }
        if (~par) cout << (par ^ 1) + 1 << " " << par + 1 << " ";
      };
      dfs(a[0] & tmp, -1);
      cout << "\n";
      return;
    }
  };
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  long long t = 1;
  if (0) cin >> t;
  for (long long i = 1; i <= t; i++) solve();
}
