Problem: Johnny's younger sister Megan had a birthday recently. Her brother has bought her a box signed as "Your beautiful necklace — do it yourself!". It contains many necklace parts and some magic glue. 

The necklace part is a chain connecting two pearls. Color of each pearl can be defined by a non-negative integer. The magic glue allows Megan to merge two pearls (possibly from the same necklace part) into one. The beauty of a connection of pearls in colors u and v is defined as follows: let 2^k be the greatest power of two dividing u ⊕ v — [exclusive or](https://en.wikipedia.org/wiki/Exclusive_or#Computer_science) of u and v. Then the beauty equals k. If u = v, you may assume that beauty is equal to 20.

Each pearl can be combined with another at most once. Merging two parts of a necklace connects them. Using the glue multiple times, Megan can finally build the necklace, which is a cycle made from connected necklace parts (so every pearl in the necklace is combined with precisely one other pearl in it). The beauty of such a necklace is the minimum beauty of a single connection in it. The girl wants to use all available necklace parts to build exactly one necklace consisting of all of them with the largest possible beauty. Help her!

Input

The first line contains n (1 ≤ n ≤ 5 ⋅ 10^5) — the number of necklace parts in the box. Each of the next n lines contains two integers a and b (0 ≤ a, b < 2^{20}), which denote colors of pearls presented in the necklace parts. Pearls in the i-th line have indices 2i - 1 and 2i respectively.

Output

The first line should contain a single integer b denoting the maximum possible beauty of a necklace built from all given parts.

The following line should contain 2n distinct integers p_i (1 ≤ p_i ≤ 2n) — the indices of initial pearls in the order in which they appear on a cycle. Indices of pearls belonging to the same necklace part have to appear at neighboring positions in this permutation (so 1 4 3 2 is not a valid output, whereas 2 1 4 3 and 4 3 1 2 are). If there are many possible answers, you can print any.

Examples

Input


5
13 11
11 1
3 5
17 1
9 27


Output


3
8 7 9 10 5 6 1 2 3 4 


Input


5
13 11
11 1
3 5
17 1
7 29


Output


2
8 7 10 9 5 6 4 3 2 1 


Input


1
1 1


Output


20
2 1 

Note

In the first example the following pairs of pearls are combined: (7, 9), (10, 5), (6, 1), (2, 3) and (4, 8). The beauties of connections equal correspondingly: 3, 3, 3, 20, 20.

The following drawing shows this construction.

<image>

Solution (in JAVA):

Solution:
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            CJohnnyAndMegansNecklace solver = new CJohnnyAndMegansNecklace();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class CJohnnyAndMegansNecklace {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();

            int[] balls = new int[n * 2];
            in.populate(balls);

//        for (int x : balls) {
//            if ((x & ((1 << 3) - 1)) == 1) {
//                debug.debug("x", x);
//            }
//        }

            int bans = -1;
            int limit = 20;
            DSU dsu = new DSU(1 << limit);
            int[] cnts = new int[1 << limit];
            for (int i = 0; i < limit; i++) {
                int mask = (1 << (i + 1)) - 1;
                dsu.reset();
                Arrays.fill(cnts, 0);
                for (int j = 0; j < n * 2; j += 2) {
                    dsu.merge(mask & balls[j], mask & balls[j + 1]);
                }
                boolean valid = true;
                for (int j = 2; valid && j < n * 2; j += 2) {
                    int prev = balls[j - 2] & mask;
                    int cur = balls[j] & mask;
                    if (dsu.find(prev) != dsu.find(cur)) {
                        valid = false;
                    }
                }

                for (int x : balls) {
                    cnts[x & mask]++;
                }

                for (int j = 0; valid && j < cnts.length; j++) {
                    if ((cnts[j] & 1) == 1) {
                        valid = false;
                    }
                }

                if (!valid) {
                    bans = i - 1;
                    break;
                }
                bans = i;
            }


            if (bans == -1) {
                out.println(0);
                for (int i = 0; i < 2 * n; i++) {
                    out.append(i + 1).append(' ');
                }
                return;
            }

            DSU ballDSU = new DSU(n);
            int[] stack = new int[1 << limit];
            Arrays.fill(stack, -1);
            int[] match = new int[n * 2];
            MultiWayDeque<int[]> groups = new MultiWayDeque<>(1 << limit, n);
            int mask = (1 << (1 + bans)) - 1;
            for (int i = 0; i < n * 2; i++) {
                int b = balls[i] & mask;
                if (stack[b] == -1) {
                    stack[b] = i;
                } else {
                    ballDSU.merge(i / 2, stack[b] / 2);
                    groups.addLast(b, new int[]{i, stack[b]});
                    addEdge(match, i, stack[b]);
                    stack[b] = -1;
                }
            }

            for (int i = 0; i < 1 << limit; i++) {
                if (groups.isEmpty(i)) {
                    continue;
                }
                int[] top = groups.removeFirst(i);
                while (!groups.isEmpty(i)) {
                    int[] head = groups.removeFirst(i);
                    if (ballDSU.find(top[0] / 2) == ballDSU.find(head[0] / 2)) {
                        continue;
                    }
                    ballDSU.merge(top[0] / 2, head[0] / 2);
                    addEdge(match, top[0], head[0]);
                    addEdge(match, top[1], head[1]);
                    top[1] = head[0];
                }
            }

            out.println(bans + 1);
            int index = 0;
            for (int i = 0; i < n; i++) {
                out.append(index + 1).append(' ');
                index ^= 1;
                out.append(index + 1).append(' ');
                index = match[index];
            }
        }

        public void addEdge(int[] match, int i, int j) {
            match[i] = j;
            match[j] = i;
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        public void populate(int[] data) {
            for (int i = 0; i < data.length; i++) {
                data[i] = readInt();
            }
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput append(char c) {
            cache.append(c);
            return this;
        }

        public FastOutput append(int c) {
            cache.append(c);
            return this;
        }

        public FastOutput println(int c) {
            return append(c).println();
        }

        public FastOutput println() {
            cache.append(System.lineSeparator());
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class DSU {
        protected int[] p;
        protected int[] rank;

        public DSU(int n) {
            p = new int[n];
            rank = new int[n];
            reset();
        }

        public final void reset() {
            for (int i = 0; i < p.length; i++) {
                p[i] = i;
                rank[i] = 0;
            }
        }

        public final int find(int a) {
            if (p[a] == p[p[a]]) {
                return p[a];
            }
            return p[a] = find(p[a]);
        }

        public final void merge(int a, int b) {
            a = find(a);
            b = find(b);
            if (a == b) {
                return;
            }
            if (rank[a] == rank[b]) {
                rank[a]++;
            }

            if (rank[a] < rank[b]) {
                int tmp = a;
                a = b;
                b = tmp;
            }

            p[b] = a;
        }

    }

    static class MultiWayDeque<V> {
        private Object[] values;
        private int[] next;
        private int[] prev;
        private int[] heads;
        private int[] tails;
        private int alloc;
        private int queueNum;

        public RevokeIterator<V> iterator(final int queue) {
            return new RevokeIterator() {
                int ele = heads[queue];


                public boolean hasNext() {
                    return ele != 0;
                }


                public Object next() {
                    Object ans = values[ele];
                    ele = next[ele];
                    return ans;
                }


                public void revoke() {
                    ele = prev[ele];
                }
            };
        }

        private void doubleCapacity() {
            int newSize = Math.max(next.length + 10, next.length * 2);
            next = Arrays.copyOf(next, newSize);
            prev = Arrays.copyOf(prev, newSize);
            values = Arrays.copyOf(values, newSize);
        }

        public void alloc() {
            alloc++;
            if (alloc >= next.length) {
                doubleCapacity();
            }
            next[alloc] = 0;
        }

        public boolean isEmpty(int qId) {
            return heads[qId] == 0;
        }

        public MultiWayDeque(int qNum, int totalCapacity) {
            values = new Object[totalCapacity + 1];
            next = new int[totalCapacity + 1];
            prev = new int[totalCapacity + 1];
            heads = new int[qNum];
            tails = new int[qNum];
            queueNum = qNum;
        }

        public void addLast(int qId, V x) {
            alloc();
            values[alloc] = x;

            if (heads[qId] == 0) {
                heads[qId] = tails[qId] = alloc;
                return;
            }
            next[tails[qId]] = alloc;
            prev[alloc] = tails[qId];
            tails[qId] = alloc;
        }

        public V removeFirst(int qId) {
            V ans = (V) values[heads[qId]];
            if (heads[qId] == tails[qId]) {
                heads[qId] = tails[qId] = 0;
            } else {
                heads[qId] = next[heads[qId]];
                prev[tails[qId]] = 0;
            }
            return ans;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < queueNum; i++) {
                builder.append(i).append(": ");
                for (Iterator<V> iterator = iterator(i); iterator.hasNext(); ) {
                    builder.append(iterator.next()).append(",");
                }
                if (builder.charAt(builder.length() - 1) == ',') {
                    builder.setLength(builder.length() - 1);
                }
                builder.append('\n');
            }
            return builder.toString();
        }

    }

    static interface RevokeIterator<E> extends Iterator<E> {
    }
}