Problem: Ujan has a lot of numbers in his boxes. He likes order and balance, so he decided to reorder the numbers.

There are k boxes numbered from 1 to k. The i-th box contains n_i integer numbers. The integers can be negative. All of the integers are distinct.

Ujan is lazy, so he will do the following reordering of the numbers exactly once. He will pick a single integer from each of the boxes, k integers in total. Then he will insert the chosen numbers — one integer in each of the boxes, so that the number of integers in each box is the same as in the beginning. Note that he may also insert an integer he picked from a box back into the same box.

Ujan will be happy if the sum of the integers in each box is the same. Can he achieve this and make the boxes perfectly balanced, like all things should be?

Input

The first line contains a single integer k (1 ≤ k ≤ 15), the number of boxes. 

The i-th of the next k lines first contains a single integer n_i (1 ≤ n_i ≤ 5 000), the number of integers in box i. Then the same line contains n_i integers a_{i,1}, …, a_{i,n_i} (|a_{i,j}| ≤ 10^9), the integers in the i-th box. 

It is guaranteed that all a_{i,j} are distinct.

Output

If Ujan cannot achieve his goal, output "No" in a single line. Otherwise in the first line output "Yes", and then output k lines. The i-th of these lines should contain two integers c_i and p_i. This means that Ujan should pick the integer c_i from the i-th box and place it in the p_i-th box afterwards.

If there are multiple solutions, output any of those.

You can print each letter in any case (upper or lower).

Examples

Input


4
3 1 7 4
2 3 2
2 8 5
1 10


Output


Yes
7 2
2 3
5 1
10 4


Input


2
2 3 -2
2 -1 5


Output


No


Input


2
2 -10 10
2 0 -20


Output


Yes
-10 2
-20 1

Note

In the first sample, Ujan can put the number 7 in the 2nd box, the number 2 in the 3rd box, the number 5 in the 1st box and keep the number 10 in the same 4th box. Then the boxes will contain numbers \{1,5,4\}, \{3, 7\}, \{8,2\} and \{10\}. The sum in each box then is equal to 10.

In the second sample, it is not possible to pick and redistribute the numbers in the required way.

In the third sample, one can swap the numbers -20 and -10, making the sum in each box equal to -10.

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.HashMap;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.io.UncheckedIOException;
import java.util.Map;
import java.io.Closeable;
import java.util.Map.Entry;
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);
            TaskC solver = new TaskC();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskC {
        SubsetGenerator sg = new SubsetGenerator();
        Node[] nodes;
        int n;
        Map<Long, Node> map;
        long notExist;
        long[] mask2Key;
        Map<Long, LongList> sequence;
        DigitUtils.BitOperator bo = new DigitUtils.BitOperator();
        boolean[] dp;

        public void solve(int testNumber, FastInput in, FastOutput out) {
            n = in.readInt();
            nodes = new Node[n];
            for (int i = 0; i < n; i++) {
                nodes[i] = new Node();
                nodes[i].id = i;
            }

            map = new LinkedHashMap<>(200000);
            for (int i = 0; i < n; i++) {
                int k = in.readInt();
                for (int j = 0; j < k; j++) {
                    long x = in.readInt();
                    map.put(x, nodes[i]);
                    nodes[i].sum += x;
                }
            }

            long total = 0;
            for (Node node : nodes) {
                total += node.sum;
            }

            if (total % n != 0) {
                out.println("No");
                return;
            }
            long avg = total / n;

            notExist = (long) 1e18;
            mask2Key = new long[1 << n];
            Arrays.fill(mask2Key, notExist);
            sequence = new HashMap<>(200000);


            for (Map.Entry<Long, Node> kv : map.entrySet()) {
                for (Node node : nodes) {
                    node.handled = false;
                }

                long key = kv.getKey();

                Node node = kv.getValue();
                node.handled = true;
                int mask = bo.setBit(0, node.id, true);

                LongList list = new LongList(15);
                list.add(key);

                long req = avg - (node.sum - key);
                boolean valid = true;

                while (true) {
                    if (req == key) {
                        break;
                    }
                    Node next = map.get(req);
                    if (next == null || next.handled) {
                        valid = false;
                        break;
                    }
                    next.handled = true;
                    list.add(req);
                    req = avg - (next.sum - req);
                    mask = bo.setBit(mask, next.id, true);
                }

                if (!valid) {
                    continue;
                }

                mask2Key[mask] = key;
                sequence.put(key, list);
            }


            dp = new boolean[1 << n];
            for (int i = 0; i < (1 << n); i++) {
                dp[i] = mask2Key[i] != notExist;
                sg.setSet(i);
                while (!dp[i] && sg.hasNext()) {
                    int next = sg.next();
                    if (next == 0 || next == i) {
                        continue;
                    }
                    dp[i] = dp[i] || (dp[next] && dp[i - next]);
                }
            }

            if (!dp[(1 << n) - 1]) {
                out.println("No");
                return;
            }

            populate((1 << n) - 1);
            out.println("Yes");
            for (Node node : nodes) {
                out.append(node.out).append(' ').append(node.to + 1).append('\n');
            }
        }

        public void populate(int mask) {
            if (mask2Key[mask] != notExist) {
                LongList list = sequence.get(mask2Key[mask]);
                int m = list.size();
                for (int i = 0; i < m; i++) {
                    long v = list.get(i);
                    long last = list.get(DigitUtils.mod(i - 1, m));
                    Node which = map.get(v);
                    Node to = map.get(last);

                    which.out = v;
                    which.to = to.id;
                }
                return;
            }

            sg.setSet(mask);
            while (sg.hasNext()) {
                int next = sg.next();
                if (next == 0 || next == mask) {
                    continue;
                }
                if (dp[next] && dp[mask - next]) {
                    populate(next);
                    populate(mask - next);
                    return;
                }
            }
        }

    }

    static class LongList {
        private int size;
        private int cap;
        private long[] data;
        private static final long[] EMPTY = new long[0];

        public LongList(int cap) {
            this.cap = cap;
            if (cap == 0) {
                data = EMPTY;
            } else {
                data = new long[cap];
            }
        }

        public LongList(LongList list) {
            this.size = list.size;
            this.cap = list.cap;
            this.data = Arrays.copyOf(list.data, size);
        }

        public LongList() {
            this(0);
        }

        private void ensureSpace(int need) {
            int req = size + need;
            if (req > cap) {
                while (cap < req) {
                    cap = Math.max(cap + 10, 2 * cap);
                }
                data = Arrays.copyOf(data, cap);
            }
        }

        private void checkRange(int i) {
            if (i < 0 || i >= size) {
                throw new ArrayIndexOutOfBoundsException();
            }
        }

        public long get(int i) {
            checkRange(i);
            return data[i];
        }

        public void add(long x) {
            ensureSpace(1);
            data[size++] = x;
        }

        public int size() {
            return size;
        }

        public String toString() {
            return Arrays.toString(Arrays.copyOf(data, size));
        }

    }

    static class SubsetGenerator {
        private int[] meanings = new int[33];
        private int[] bits = new int[33];
        private int remain;
        private int next;

        public void setSet(int set) {
            int bitCount = 0;
            while (set != 0) {
                meanings[bitCount] = set & -set;
                bits[bitCount] = 0;
                set -= meanings[bitCount];
                bitCount++;
            }
            remain = 1 << bitCount;
            next = 0;
        }

        public boolean hasNext() {
            return remain > 0;
        }

        private void consume() {
            remain = remain - 1;
            int i;
            for (i = 0; bits[i] == 1; i++) {
                bits[i] = 0;
                next -= meanings[i];
            }
            bits[i] = 1;
            next += meanings[i];
        }

        public int next() {
            int returned = next;
            consume();
            return returned;
        }

    }

    static class Node {
        int id;
        long sum;
        boolean handled;
        long out;
        long to;

    }

    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;
        }

        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 {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        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(long c) {
            cache.append(c);
            return this;
        }

        public FastOutput println(String c) {
            cache.append(c).append('\n');
            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 DigitUtils {
        private static final long[] DIGIT_VALUES = new long[19];

        static {
            DIGIT_VALUES[0] = 1;
            for (int i = 1; i < 19; i++) {
                DIGIT_VALUES[i] = DIGIT_VALUES[i - 1] * 10;
            }
        }

        private DigitUtils() {
        }

        public static int mod(int x, int mod) {
            x %= mod;
            if (x < 0) {
                x += mod;
            }
            return x;
        }

        public static class BitOperator {
            public int setBit(int x, int i, boolean v) {
                if (v) {
                    x |= 1 << i;
                } else {
                    x &= ~(1 << i);
                }
                return x;
            }

        }

    }
}