import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Map;
import java.io.BufferedReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskC solver = new TaskC();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskC {
        int n;
        long neededSum;
        long[] sums;
        Map<Long, Integer> where;

        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            n = in.nextInt();
            int[][] a = new int[n][];
            neededSum = 0;
            sums = new long[n];
            for (int i = 0; i < n; i++) {
                int k = in.nextInt();
                a[i] = new int[k];
                for (int j = 0; j < k; j++) {
                    a[i][j] = in.nextInt();
                    neededSum += a[i][j];
                    sums[i] += a[i][j];
                }
            }

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

            where = new HashMap<>();
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < a[i].length; j++) {
                    where.put((long) a[i][j], i);
                }
            }

            Entry[][] cycleSol = new Entry[1 << n][];
            List<Entry> sol = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                for (int x : a[i]) {
                    search(i, i, x, x, 0, 0, sol, cycleSol);
                }
            }

            boolean[] can = new boolean[1 << n];
            int[] via = new int[1 << n];
            can[0] = true;
            for (int mask = 0; mask < 1 << n; mask++) {
                for (int submask = mask; submask > 0; submask = (submask - 1) & mask) {
                    if (cycleSol[submask] != null && can[mask ^ submask]) {
                        can[mask] = true;
                        via[mask] = submask;
                    }
                }
            }

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

            int[][] ans = new int[n][2];
            for (int mask = (1 << n) - 1; mask > 0; ) {
                int sm = via[mask];
                mask ^= sm;

                for (Entry e : cycleSol[sm]) {
                    ans[e.from][0] = e.what;
                    ans[e.from][1] = e.to + 1;
                }
            }

            out.println("Yes");
            for (int i = 0; i < n; i++) {
                out.println(ans[i][0] + " " + ans[i][1]);
            }
        }

        private void search(int start, int cur, long fromStart, long fromCur, int hasIn, int hasOut, List<Entry> sol, Entry[][] cycleSol) {
            for (int i = start; i < n; i++) {
                if ((hasIn & (1 << i)) > 0) {
                    continue;
                }
                if ((hasOut & (1 << cur)) > 0) {
                    continue;
                }
                long fromI = sums[i] + fromCur - neededSum;
                Integer w = where.get(fromI);
                if (w == null || w != i) {
                    continue;
                }
                sol.add(new Entry(cur, i, (int) fromCur));
                int nHasIn = hasIn | (1 << i);
                int nHasOut = hasOut | (1 << cur);
                if (i == start && fromI == fromStart) {
                    cycleSol[nHasOut] = sol.toArray(new Entry[0]);
                }
                search(start, i, fromStart, fromI, nHasIn, nHasOut, sol, cycleSol);
                sol.remove(sol.size() - 1);
            }
        }

        class Entry {
            int from;
            int to;
            int what;

            Entry(int from, int to, int what) {
                this.from = from;
                this.to = to;
                this.what = what;
            }

            public String toString() {
                return from + " " + to + " " + what;
            }

        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    String rl = in.readLine();
                    if (rl == null) {
                        return null;
                    }
                    st = new StringTokenizer(rl);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


//package round599;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.Map;

public class C {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		int[][] a = new int[n][];
		Map<Long, Long> ci = new HashMap<>();
		long[] sums = new long[n];
		for(int i = 0;i < n;i++){
			int K = ni();
			a[i] = na(K);
			for(int j = 0;j < K;j++){
				ci.put((long)a[i][j], (long)i<<32|j);
				sums[i] += a[i][j];
			}
		}

		long S = 0;
		for(long v : sums){
			S += v;
		}
		if(S % n != 0){
			out.println("No");
			return;
		}
		S /= n;

		int[] offsets = new int[n+1];
		for(int i = 0;i < n;i++){
			offsets[i+1] = offsets[i] + a[i].length;
		}

		int m = offsets[n];
		int[] f = new int[m];
		Arrays.fill(f, -1);
		for(int i = 0;i < n;i++){
			for(int j = 0;j < a[i].length;j++){
				long T = a[i][j] + S - sums[i];
				if(ci.containsKey(T)){
					long code = ci.get(T);
					int from = offsets[i] + j;
					int to = offsets[(int)(code>>>32)] + (int)code;
					if(from != to && i == (int)(code>>>32))continue;
					f[from] = to;
				}
			}
		}
		int[][] cs = getCycles(f);
		int[][] zcs = new int[1<<n][];
		for(int[] c : cs){
			int ptn = 0;
			for(int k : c){
				int ind = Arrays.binarySearch(offsets, k);
				if(ind < 0)ind = -ind-2;
				ptn |= 1<<ind;
			}
			if(Integer.bitCount(ptn) != c.length)continue;
			zcs[ptn] = c;
		}

		boolean[] dp = new boolean[1<<n];
		dp[0] = true;
		for(int i = 1;i < 1<<n;i++){
			if(zcs[i] != null){
				int mask = (1<<n)-1^i;
				for(int j = mask;j >= 0;j--){ j &= mask;
					dp[i|j] |= dp[j];
				} // include j=0
			}
		}
		if(dp[(1<<n)-1]){
			int[] vals = new int[n];
			int[] tos = new int[n];

			int cur = (1<<n)-1;
			inner:
			while(cur > 0){
				for(int k = cur;k >= 0;k--){
					k &= cur;
					if(dp[cur^k] && zcs[k] != null){
						for(int l = 0;l < zcs[k].length;l++){
							int nl = (l+zcs[k].length-1) % zcs[k].length;
							int fclus = Arrays.binarySearch(offsets, zcs[k][l]);
							int tclus = Arrays.binarySearch(offsets, zcs[k][nl]);
							if(fclus < 0)fclus = -fclus-2;
							if(tclus < 0)tclus = -tclus-2;
							int val = a[fclus][zcs[k][l]-offsets[fclus]];
							vals[fclus] = val;
							tos[fclus] = tclus;
						}
						cur ^= k;
						continue inner;
					}
				}
			}

			out.println("Yes");
			for(int i = 0;i < n;i++){
				out.println(vals[i] + " " + (tos[i]+1));
			}

//			for(int i = 0;i < n;i++){
//				sums[i] -= vals[i];
//				sums[tos[i]] += vals[i];
//			}
//
//			for(int i = 0;i < n;i++){
//				assert sums[i] == S;
//			}

		}else{
			out.println("No");
		}
	}

	int[][] getCycles(int[] f)
	{
		int n = f.length;
		int[][] ret = new int[n][];
		boolean[] ved = new boolean[n];
		int[] touched = new int[n];
		Arrays.fill(touched, -1);
		int[] path = new int[n];
		int q = 0;
		outer:
		for(int i = 0;i < n;i++){
			int p = 0;
			for(int j = i;j != -1;j = f[j]){
				if(touched[j] != -1){
					ret[q++] = Arrays.copyOfRange(path, touched[j], p);
					break;
				}
				if(ved[j])break;
				touched[j] = p;
				path[p++] = j;
				ved[j] = true;
			}
			for(int k = 0;k < p;k++){
				touched[path[k]] = -1;
			}
		}
		return Arrays.copyOf(ret, q);
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new C().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Random;
import java.util.TreeSet;

public final class CF_599_D1_C
{

	static boolean verb=true;
	static void log(Object X){if (verb) System.err.println(X);}
	static void log(Object[] X){if (verb) {for (Object U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X){if (verb) {for (int U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X,int L){if (verb) {for (int i=0;i<L;i++) System.err.print(X[i]+" ");System.err.println("");}}
	static void log(long[] X){if (verb) {for (long U:X) System.err.print(U+" ");System.err.println("");}}

	static void logWln(Object X){if (verb) System.err.print(X);}
	static void info(Object o){	System.out.println(o);}
	static void output(Object o){outputWln(""+o+"\n");	}
	static void outputWln(Object o){try {out.write(""+ o);} catch (Exception e) {}}

	static long mod=1000000007;

	// Global vars
	static BufferedWriter out;
	static InputReader reader;

	static class Composite implements Comparable<Composite>{
		int idx;
		int v;

		public int compareTo(Composite X) {
			if (v!=X.v)
				return v-X.v;
			return idx-X.idx;

		}

		public Composite(int idx, int v) {
			this.idx = idx;
			this.v = v;
		}

	}

	static void test() {
		log("testing");

		log("done");

	}

	static void explore(ArrayList<Integer>[] components,ArrayList<Integer> bob,int[][] move,ArrayList<int[]>[] howto,int[][] list) {

		for (int x:bob) {
			if (components[x].size()==1) {
				int tm[]=howto[x].get(0);

				int L=howto[x].size();
				howto[x].add(tm);
				for (int i=0;i<L;i++) {
					int[] cur=howto[x].get(i);
					int[] nx=howto[x].get(i+1);
					int a=cur[0];
					int a2=nx[0];
					int b2=nx[1];
					move[a2][0]=list[a2][b2];
					move[a2][1]=a;
				}

			} else {
				explore(components,components[x],move,howto,list);
			}
		}
	}

	static void process() throws Exception {

		//arrayTest();

		out = new BufferedWriter(new OutputStreamWriter(System.out));
		reader = new InputReader(System.in);

		int k=reader.readInt();
		int[][] list=new int[k][];
		long[] sum=new long[k];
		int[] L=new int[k];
		HashMap<Integer,int[]> target=new HashMap<Integer,int[]>();
		long tot=0;
		for (int i=0;i<k;i++) {
			L[i]=reader.readInt();
			list[i]=new int[L[i]];
			for (int j=0;j<L[i];j++) {
				list[i][j]=reader.readInt();
				sum[i]+=list[i][j];
				target.put(list[i][j],new int[] {i,j});
			}
			tot+=sum[i];
		}

		int MX=1<<k;
		int AX=1000000001;
		ArrayList<int[]>[] howto=new ArrayList[MX];

		log("ok with the data");

		if (tot%k!=0) {
			output("No");
		} else {

			tot/=k;

			for (int i=0;i<k;i++) {

				if (sum[i]==tot) {
					//log("nothing to do for i:"+i);
					// nothing to do
					int mask=1<<i;
					ArrayList<int[]> cand=new ArrayList<int[]>();
					cand.add(new int[] {i,0});
					howto[mask]=cand;
				} else

					for (int j=0;j<L[i];j++) {
						int u=i;
						int v=j;
						boolean ok=true;
						int src_u=u;
						int src_v=v;
						int mask=0;
						boolean goon=true;
						ArrayList<int[]> cand=new ArrayList<int[]>();
						//log("start loop");
						while (goon) {
							cand.add(new int[] {u,v});
							//log("u:"+u+" v:"+v);
							ok=false;
							goon=false;
							long need=tot-((long)sum[u]-(long)list[u][v]);
							if (Math.abs(need)<=AX) {
								//log("need:"+need);
								int nd=(int)need;
								int[] tm=target.get(nd);
								//log("tm:"+tm);
								if (tm!=null) {
									//log("can find successor");
									int nxu=tm[0];
									int nxv=tm[1];
									if ((mask&(1<<nxu))==0) {
										mask|=1<<nxu;
										if (nxu==src_u) {
											// looping back to source
											if (nxv==src_v)
												ok=true;
										} else {
											u=nxu;
											v=nxv;
											ok=true;
											goon=true;
										}
									}
								}
							}
						}
						if (ok) {
							if (howto[mask]==null) {

								howto[mask]=cand;

							}
						}
					}
			}

			log("step 1 done");

			// now mask

			ArrayList[] components=new ArrayList[MX];

			for (int m=0;m<MX;m++) {
				if (howto[m]!=null) {
					//String s=Integer.toBinaryString(m);
					//while (s.length()<k)
					//	s="0"+s;
					//log("found mask:"+s);
					components[m]=new ArrayList<Integer>();
					components[m].add(m);
				}
			}

			int[] msk=new int[MX];
			int w=0;

			for (int a=0;a<MX;a++) {
				if (howto[a]!=null) {
					ArrayList<Integer> add=new ArrayList<Integer>();

					int ww=w;
					for (int i=0;i<ww;i++) {
						int b=msk[i];
						if ((b&a)==0) {

							int c=b|a;
							//log("creating c:"+c+" ");
							if (components[c]==null ) {
								components[c]=new ArrayList<Integer>();
								components[c].add(a);
								components[c].add(b);
								msk[w++]=c;
							}
						}
					}
					msk[w++]=a;
				}
			}
			//log("msk:"+msk);
			//log(components[MX-1]);
			if (components[MX-1]!=null) {
				output("Yes");
				int[][] move=new int[k][2];
				explore(components,components[MX-1],move,howto,list);
				for (int i=0;i<k;i++) {
					output(move[i][0]+" "+(move[i][1]+1));
				}

			} else {
				output("No");
			}

		}

		try {
			out.close();
		} catch (Exception e) {
		}

	}

	public static void main(String[] args) throws Exception {
		process();

	}

	static final class InputReader {
		private final InputStream stream;
		private final byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		private int read() throws IOException {
			if (curChar >= numChars) {
				curChar = 0;
				numChars = stream.read(buf);
				if (numChars <= 0) {
					return -1;
				}
			}
			return buf[curChar++];
		}

		public final String readString() throws IOException {
			int c = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			StringBuilder res = new StringBuilder();
			do {
				res.append((char) c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public final int readInt() throws IOException {
			int c = read();
			boolean neg = false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d = (char) c;
			// log("d:"+d);
			if (d == '-') {
				neg = true;
				c = read();
			}
			int res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			// log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		public final long readLong() throws IOException {
			int c = read();
			boolean neg = false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d = (char) c;
			// log("d:"+d);
			if (d == '-') {
				neg = true;
				c = read();
			}
			long res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			// log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		private boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}
	}

}


import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.BiFunction;

public class Main{
	static Scanner scn = new Scanner(System.in);
	static FastScanner sc = new FastScanner();
	static Mathplus mp = new Mathplus();
	static PrintWriter ot = new PrintWriter(System.out);
	static Random rand = new Random();
	static int mod = 1000000007;
	static long inf = (long)1e17;
	static int[] dx = {0,1,0,-1};
	static int[] dy = {1,0,-1,0};
	static int max;
	public static void main(String[] args) {

		int N = sc.nextInt();
		ArrayList<Integer>[] l = new ArrayList[N];
		HashMap<Long,Integer> map = new HashMap<Long,Integer>();
		long sum = 0;
		long[] s = new long[N];
		for(int i=0;i<N;i++) {
			l[i] = new ArrayList<Integer>();
			int n = sc.nextInt();
			for(int j=0;j<n;j++) {
				int a = sc.nextInt();
				map.put((long)a, i);
				s[i] += a;
				sum += a;
				l[i].add(a);
			}
		}
		if(Math.abs(sum)%N!=0) {
			System.out.println("NO");
			return;
		}
		long make = sum/N;
		boolean[] dp = new boolean[(1<<N)];
		int[] first = new int[(1<<N)];
		int[] bef = new int[(1<<N)];

		Arrays.fill(first,mod);
		for(int i=0;i<N;i++) {
			for(int a:l[i]) {
				int used = 0;
				boolean f = true;
				long now = a;
				int see = i;
				while(true) {
					long next = make-(s[see]-now);

					if(next==a) {
						break;
					}
					if(!map.containsKey(next)) {
						f = false;
						break;
					}else {
						int k = map.get(next);
						if(mp.contains(used,k)&&k!=i) {
							f = false;
							break;
						}else {
							used = mp.bitadd(used,k);
							now = next;
							see = k;
						}
					}
				}
				if(f) {
					dp[mp.bitadd(used,i)] = true;
					first[mp.bitadd(used,i)] = a;
				}
			}
		}

		dp[0] = true;
		for(int i=1;i<(1<<N);i++) {
			for(int j=i;j>0;j=(j-1)&i) {
				if(dp[i^j]&&dp[j]) {
					dp[i]=true;
					bef[i] = j;
				}
			}
		}

		if(!dp[(1<<N)-1]) {
			System.out.println("NO");
		}else {
			System.out.println("YES");
			ArrayDeque<Integer> q = new ArrayDeque<Integer>();
			int[] ans1 = new int[N];
			int[] ans2 = new int[N];
			q.add((1<<N)-1);
			while(!q.isEmpty()) {
				int Q = q.poll();
				if(first[Q]==mod) {
					q.add(bef[Q]);
					q.add(Q^bef[Q]);
				}else {

					int a = first[Q];
					long now = a;
					int befo = map.get((long)a);
					while(true) {
						long next = make-(s[befo]-now);
						if(next==a) {
							int k = map.get(next);
							ans1[k] = (int)next;
							ans2[k] = befo;
							break;
						}
						int k = map.get(next);
						ans1[k] = (int)next;
						ans2[k] = befo;
						now = next;
						befo = k;
					}
				}
			}
			for(int i=0;i<N;i++) {
				System.out.println(ans1[i]+" "+(ans2[i]+1));
			}

		}

	}

}
class GridGraph extends Graph{

	int N;
	int M;
	String[] S;
	HashMap<Character,Integer> map;
	GridGraph(int n,int m,String[] s,char[] c){
		super(n*m);
		N = n;
		M = m;
		S = s;
		map = new HashMap<Character,Integer>();
		for(int i=0;i<n-1;i++) {
			for(int j=0;j<m;j++) {
				if(S[i].charAt(j)!='#'&&S[i+1].charAt(j)!='#') {
					addEdge(toint(i,j),toint(i+1,j));
					addEdge(toint(i+1,j),toint(i,j));
				}
			}
		}
		for(int i=0;i<n;i++) {
			for(int j=0;j<m-1;j++) {
				if(S[i].charAt(j)!='#'&&S[i].charAt(j+1)!='#') {
					addEdge(toint(i,j),toint(i,j+1));
					addEdge(toint(i,j+1),toint(i,j));

				}
			}
		}
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				for(int k=0;k<c.length;k++) {
					if(S[i].charAt(j)==c[k])map.put(c[k],toint(i,j));
				}
			}
		}
	}

	int toint(int i,int j) {
		return i*M+j;
	}

}

class BetterGridGraph{
	int N;
	int M;
	char[][] S;
	HashMap<Character,Integer> map;
	int[] dx = {0,1,0,-1};
	int[] dy = {1,0,-1,0};
	char w;
	char b = '#';
	BetterGridGraph(int n,int m,String[] s,char[] c){

		N = n;
		M = m;
		for(int i=0;i<s.length;i++) {
			S[i] = s[i].toCharArray();
		}
		map = new HashMap<Character,Integer>();
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				for(int k=0;k<c.length;k++) {
					if(S[i][j]==c[k])map.put(c[k],toint(i,j));
				}
			}
		}
	}
	BetterGridGraph(int n,int m,char[][] s,char[] c){

		N = n;
		M = m;
		S = s;
		map = new HashMap<Character,Integer>();
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				for(int k=0;k<c.length;k++) {
					if(S[i][j]==c[k])map.put(c[k],toint(i,j));
				}
			}
		}
	}

	BetterGridGraph(int n,int m,String[] s,char[] c,char W,char B){

		N = n;
		M = m;
		for(int i=0;i<s.length;i++) {
			S[i] = s[i].toCharArray();
		}
		w = W;
		b = B;
		map = new HashMap<Character,Integer>();
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				for(int k=0;k<c.length;k++) {
					if(S[i][j]==c[k])map.put(c[k],toint(i,j));
				}
			}
		}
	}
	BetterGridGraph(int n,int m,char[][] s,char[] c,char W,char B){

		N = n;
		M = m;
		S = s;
		w = W;
		b = B;
		map = new HashMap<Character,Integer>();
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				for(int k=0;k<c.length;k++) {
					if(S[i][j]==c[k])map.put(c[k],toint(i,j));
				}
			}
		}
	}

	int toint(int i,int j) {
		return i*M+j;
	}

	int[] bfs(char C) {
		int s = map.get(C);
		int[] L = new int[N*M];
		for(int i=0;i<N*M;i++){
			L[i] = -1;
		}
		L[s] = 0;
		ArrayDeque<Integer> Q = new ArrayDeque<Integer>();
		Q.add(s);
		Range X = new Range(0,N-1);
		Range Y = new Range(0,M-1);
		while(!Q.isEmpty()){
			int v = Q.poll();
			for(int i=0;i<4;i++){
				int x = v/M;
				int y = v%M;
				int nx = x+dx[i];
				int ny = y+dy[i];
				if(X.isIn(nx)&&Y.isIn(ny)&&S[nx][ny]!=b) {
					int w = toint(nx,ny);
					if(L[w]==-1){
						L[w] = L[v] + 1;
						Q.add(w);
					}
				}
			}
		}
		return L;
	}

	int[][] bfs2(char C,int K){
		int s = map.get(C);
		int[][] L = new int[N*M][K+1];
		for(int i=0;i<N*M;i++){
			for(int j=0;j<=K;j++)
			L[i][j] = 1000000007;
		}
		L[s][0] = 0;
		ArrayDeque<IntIntPair> Q = new ArrayDeque<IntIntPair>();
		Q.add(new IntIntPair(s,0));
		Range X = new Range(0,N-1);
		Range Y = new Range(0,M-1);
		while(!Q.isEmpty()){
			IntIntPair v = Q.poll();
			for(int i=0;i<4;i++){
				int x = v.a/M;
				int y = v.a%M;
				int h = v.b;
				int nx = x+dx[i];
				int ny = y+dy[i];
				if(X.isIn(nx)&&Y.isIn(ny)&&S[nx][ny]!=b) {
					int ni = toint(nx,ny);
					int nh = S[nx][ny]==w?h+1:h;
					if(nh>K) continue;
					if(L[ni][nh]==1000000007){
						L[ni][nh] = L[v.a][h] + 1;
						Q.add(new IntIntPair(ni,nh));
					}
				}
			}
		}
		for(int i=0;i<N*M;i++) {
			for(int j=1;j<=K;j++) {
				L[i][j] = Math.min(L[i][j],L[i][j-1]);
			}
		}
		return L;
	}
}

class StringManager{
	ArrayList<Character> S;
	static Mathplus mp;
	static boolean calced;
	static int base;
	static long baserev;
	ArrayList<Long> l;
	StringManager(String s){
		S = new ArrayList<Character>();
		for(int i=0;i<s.length();i++) {
			S.add(s.charAt(i));
		}
		if(!calced) {
			calced = true;
			mp = new Mathplus();
			base = 1000003;
			baserev = mp.rev(base);
			mp.buildpow(base,1000050);
			mp.buildrevpow((int) baserev,1000050);

		}
		l = new ArrayList<Long>();

		l.add((long)S.get(0));

		for(int i=1;i<S.size();i++) {
			char c = S.get(i);
			l.add((l.get(i-1) + mp.pow[i] * c)%mp.mod);

		}
	}
	void add(char C){
		int i = S.size();
		S.add(C);
		l.add((l.get(i-1) + mp.pow[i] * C)%mp.mod);
	}
	long gethash(int le,int ri) {
		long res = l.get(ri);
		if(le!=0) {
			res -= l.get(le-1);
			res += mp.mod;
			res %= mp.mod;
			res *= mp.revpow[le];
			res %= mp.mod;
		}
		return res;
	}

}

class Trie{
	int nodenumber = 1;
	ArrayList<TrieNode> l;
	Trie(){
		l = new ArrayList<TrieNode>();
		l.add(new TrieNode());
	}

	void add(String S,int W){
		int now = 0;
		for(int i=0;i<S.length();i++) {
			TrieNode n = l.get(now);
			char c = S.charAt(i);
			if(n.Exist[c-'a']!=-1) {
				now = n.Exist[c-'a'];
			}else {
				l.add(new TrieNode());
				n.Exist[c-'a'] = nodenumber;
				now = nodenumber;
				nodenumber++;
			}
		}
		l.get(now).weight = W;
	}

	void find(String S,int i,int[] dp) {
		int now = 0;
		dp[i+1] = Math.max(dp[i],dp[i+1]);
		for(int j=0;;j++) {
			TrieNode n = l.get(now);
			dp[i+j] = Math.max(dp[i+j],dp[i]+n.weight);
			int slook = i+j;
			if(slook>=S.length())return;
			char c = S.charAt(slook);
			if(n.Exist[c-'a']==-1)return;
			now = n.Exist[c-'a'];
		}
	}
}

class TrieNode{

	int[] Exist = new int[26];
	int weight = 0;
	TrieNode(){
		for(int i=0;i<26;i++) {
			Exist[i] = -1;
		}
	}
}

class SizeComparator implements Comparator<Edge>{
	int[] size;
	SizeComparator(int[] s) {
		size = s;
	}

	public int compare(Edge o1, Edge o2) {
		return size[o1.to]-size[o2.to];

	}

}

class ConvexHullTrick {
	long[] A, B;
	int len;

	public ConvexHullTrick(int n) {
		A = new long[n];
		B = new long[n];
	}

	private boolean check(long a, long b) {
		return (B[len - 2] - B[len - 1]) * (a - A[len - 1]) >= (B[len - 1] - b) * (A[len - 1] - A[len - 2]);
	}

	public void add(long a, long b) {
		while (len >= 2 && check(a, b)) {
			len--;
		}
		A[len] = a;
		B[len] = b;
		len++;
	}

	public long query(long x) {
		int l = -1, r = len - 1;
		while (r - l > 1) {
			int mid = (r + l) / 2;
			if (get(mid,x)>=get(mid+1,x)) {
				l = mid;
			} else {
				r = mid;
			}
		}
		return get(r,x);
	}

	private long get(int k, long x) {
		return A[k] * x + B[k];
	}
}

class Range{
	int l;
	int r;
	int length;
	Range(int L,int R){
		l = L;
		r = R;
		length = R-L+1;
	}

	boolean isIn(int x) {
		return (l<=x&&x<=r);

	}
}
class LeftComparator implements Comparator<Range>{
	public int compare(Range P, Range Q) {
		return P.l-Q.l;
	}
}
class RightComparator implements Comparator<Range>{
	public int compare(Range P, Range Q) {
		return P.r-Q.r;
	}
}
class LengthComparator implements Comparator<Range>{
	public int compare(Range P, Range Q) {
		return P.length-Q.length;
	}
}
class SegmentTree<T,E>{
	int N;
	BiFunction<T,T,T> f;
	BiFunction<T,E,T> g;
	T d1;
	ArrayList<T> dat;
	SegmentTree(BiFunction<T,T,T> F,BiFunction<T,E,T> G,T D1,T[] v){
		int n = v.length;
		f = F;
		g = G;
		d1 = D1;
		init(n);
		build(v);
	}

	void init(int n) {
		N = 1;
		while(N<n)N*=2;
		dat = new ArrayList<T>();
	}

	void build(T[] v) {
		for(int i=0;i<2*N;i++) {
			dat.add(d1);
		}
		for(int i=0;i<v.length;i++) {
			dat.set(N+i-1,v[i]);
		}
		for(int i=N-2;i>=0;i--) {
			dat.set(i,f.apply(dat.get(i*2+1),dat.get(i*2+2)));
		}
	}

	void update(int k,E a) {
		k += N-1;
		dat.set(k,g.apply(dat.get(k),a));
		while(k>0){
			k = (k-1)/2;
			dat.set(k,f.apply(dat.get(k*2+1),dat.get(k*2+2)));
		}
	}

	T query(int a,int b, int k, int l ,int r) {
		if(r<=a||b<=l) return d1;
		if(a<=l&&r<=b) return dat.get(k);
		T vl = query(a,b,k*2+1,l,(l+r)/2);
		T vr = query(a,b,k*2+2,(l+r)/2,r);
		return f.apply(vl, vr);
	}
	T query(int a,int b){
		return query(a,b,0,0,N);
	}

}

class LazySegmentTree<T,E> extends SegmentTree<T,E>{
	BiFunction<E,E,E> h;
	BiFunction<E,Integer,E> p = (E a,Integer b) ->{return a;};
	E d0;
	ArrayList<E> laz;
	LazySegmentTree(BiFunction<T,T,T> F,BiFunction<T,E,T> G,BiFunction<E,E,E> H,T D1,E D0,T[] v){
		super(F,G,D1,v);
		int n = v.length;
		h = H;
		d0 = D0;
		Init(n);
	}
	void build() {

	}
	void Init(int n){
		laz = new ArrayList<E>();
		for(int i=0;i<2*N;i++) {
			laz.add(d0);
		}
	}

	void eval(int len,int k) {
		if(laz.get(k).equals(d0)) return;
		if(k*2+1<N*2-1) {
			laz.set(k*2+1,h.apply(laz.get(k*2+1),laz.get(k)));
			laz.set(k*2+2,h.apply(laz.get(k*2+2),laz.get(k)));
		}
		dat.set(k,g.apply(dat.get(k), p.apply(laz.get(k), len)));
		laz.set(k,d0);
	}

	T update(int a,int b,E x,int k,int l,int r) {
		eval(r-l,k);
		if(r<=a||b<=l) {
			return dat.get(k);
		}
		if(a<=l&&r<=b) {
			laz.set(k,h.apply(laz.get(k),x));
			return g.apply(dat.get(k),p.apply(laz.get(k),r-l));
		}
		T vl = update(a,b,x,k*2+1,l,(l+r)/2);
		T vr = update(a,b,x,k*2+2,(l+r)/2,r);
		dat.set(k,f.apply(vl,vr));
		return dat.get(k);

	}

	T update(int a,int b,E x) {
		return update(a,b,x,0,0,N);
	}

	T query(int a,int b,int k,int l,int r) {
		eval(r-l,k);
		if(r<=a||b<=l) return d1;
		if(a<=l&&r<=b) return dat.get(k);

		T vl = query(a,b,k*2+1,l,(l+r)/2);
		T vr = query(a,b,k*2+2,(l+r)/2,r);
		return f.apply(vl, vr);
	}

	T query(int a,int b){
		return query(a,b,0,0,N);
	}

}

class AddSumSegmentTree{
	int N;
	int d1;
	ArrayList<Integer> dat;
	AddSumSegmentTree(int[] v){
		int n = v.length;
		init(n);
		build(v);
	}

	void init(int n) {
		N = 1;
		while(N<n)N*=2;
		dat = new ArrayList<Integer>();
	}

	void build(int[] v) {
		for(int i=0;i<2*N;i++) {
			dat.add(d1);
		}
		for(int i=0;i<v.length;i++) {
			dat.set(N+i-1,v[i]);
		}
		for(int i=N-2;i>=0;i--) {
			dat.set(i,dat.get(i*2+1)+dat.get(i*2+2));
		}
	}

	void update(int k,int a) {
		k += N-1;
		dat.set(k,dat.get(k)+a);
		while(k>0){
			k = (k-1)/2;
			dat.set(k,dat.get(k*2+1)+dat.get(k*2+2));
		}
	}

	int query(int a,int b, int k, int l ,int r) {
		if(r<=a||b<=l) return d1;
		if(a<=l&&r<=b) return dat.get(k);
		int vl = query(a,b,k*2+1,l,(l+r)/2);
		int vr = query(a,b,k*2+2,(l+r)/2,r);
		return vl+vr;
	}
	int query(int a,int b){
		return query(a,b,0,0,N);
	}
}
class AddSumLazySegmentTree {
	int N;
	long[] dat;
	long[] laz;
	AddSumLazySegmentTree(long[] v){
		init(v.length);

		for(int i=0;i<v.length;i++) {
			dat[N+i-1]=v[i];
		}
		for(int i=N-2;i>=0;i--) {
			dat[i]=dat[i*2+1]+dat[i*2+2];
		}
	}

	void init(int n) {
		N = 1;
		while(N<n)N*=2;
		dat = new long[2*N];
		laz = new long[2*N];
	}

	void eval(int len,int k) {
		if(laz[k]==0) return;
		if(k*2+1<N*2-1) {
			laz[k*2+1] += laz[k];
			laz[k*2+2] += laz[k];
		}
		dat[k] += laz[k] * len;
		laz[k] = 0;
	}

	long update(int a,int b,long x,int k,int l,int r) {
		eval(r-l,k);
		if(r<=a||b<=l) {
			return dat[k];
		}
		if(a<=l&&r<=b) {
			laz[k] += x;
			return dat[k]+laz[k]*(r-l);
		}
		long vl = update(a,b,x,k*2+1,l,(l+r)/2);
		long vr = update(a,b,x,k*2+2,(l+r)/2,r);
		return dat[k] = vl+vr;

	}

	long update(int a,int b,long x) {
		return update(a,b,x,0,0,N);
	}

	long query(int a,int b,int k,int l,int r) {
		eval(r-l,k);
		if(r<=a||b<=l) return 0;
		if(a<=l&&r<=b) return dat[k];

		long vl = query(a,b,k*2+1,l,(l+r)/2);
		long vr = query(a,b,k*2+2,(l+r)/2,r);
		return vl+vr;
	}

	long query(int a,int b){
		return query(a,b,0,0,N);
	}

}

class BinaryIndexedTree{
	int[] val;
	BinaryIndexedTree(int N){
		val = new int[N+1];
	}
	long sum(int i) {
		if(i==0)return 0;
		long s = 0;
		while(i>0) {
			s += val[i];
			i -= i & (-i);
		}
		return s;
	}
	void add(int x,int i) {
		if(i==0)return;
		while(i<val.length){
			val[i] += x;
			i += i & (-i);
		}
	}
}

class UnionFindTree {
	int[] root;
	int[] rank;
	int[] size;
	int[] edge;
	int num;
	UnionFindTree(int N){
		root = new int[N];
		rank = new int[N];
		size = new int[N];
		edge = new int[N];
		num = N;
		for(int i=0;i<N;i++){
			root[i] = i;
			size[i] = 1;
		}
	}
	public boolean isRoot(int x) {
		return x==find(x);
	}
	public int extraEdge(int x) {
		int r = find(x);
		return edge[r] - size[r] + 1;
	}
	public int find(int x){
		if(root[x]==x){
			return x;
		}else{
			return find(root[x]);
		}
	}

	public void unite(int x,int y){
		x = find(x);
		y = find(y);
		if(x==y){
			edge[x]++;
			return;
		}else{
			num--;
			if(rank[x]<rank[y]){
				root[x] = y;
				size[y] += size[x];
				edge[y] += edge[x]+1;
			}else{
				root[y] = x;
				size[x] += size[y];
				edge[x] += edge[y]+1;
				if(rank[x]==rank[y]){
					rank[x]++;
				}
			}
		}
	}

	public boolean same(int x,int y){
		return find(x)==find(y);
	}

}

class ParticalEternalLastingUnionFindTree extends UnionFindTree{
	int[] time;
	int now;
	ParticalEternalLastingUnionFindTree(int N){
		super(N);
		time = new int[N];
		for(int i=0;i<N;i++) {
			time[i] = 1000000007;
		}
	}

	public int find(int t,int i) {
		if(time[i]>t) {
			return i;
		}else {
			return find(t,root[i]);
		}
	}

	public void unite(int x,int y,int t) {
		now = t;
		x = find(t,x);
		y = find(t,y);
		if(x==y)return;
		if(rank[x]<rank[y]){
			root[x] = y;
			size[y] += size[x];
			time[x] = t;
		}else{
			root[y] = x;
			size[x] += size[y];
			if(rank[x]==rank[y]){
				rank[x]++;
			}
			time[y] = t;
		}
	}

	public int sametime(int x,int y) {
		if(find(now,x)!=find(now,y)) return -1;
		int ok = now;
		int ng = 0;
		while(ok-ng>1) {
			int mid = (ok+ng)/2;
			if(find(mid,x)==find(mid,y)) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}

}
class Graph {
	ArrayList<Edge>[] list;
	int size;
	TreeSet<LinkEdge> Edges = new TreeSet<LinkEdge>(new LinkEdgeComparator());

	@SuppressWarnings("unchecked")
	Graph(int N){
		size = N;
		list = new ArrayList[N];
		for(int i=0;i<N;i++){
			list[i] = new ArrayList<Edge>();
		}
	}

	void addEdge(int a,int b){
		list[a].add(new Edge(b,1));
	}

	void addWeightedEdge(int a,int b,long c){
		list[a].add(new Edge(b,c));
	}

	void addEgdes(int[] a,int[] b){

		for(int i=0;i<a.length;i++){
			list[a[i]].add(new Edge(b[i],1));
		}
	}

	void addWeighterEdges(int[] a ,int[] b ,int[] c){
		for(int i=0;i<a.length;i++){
			list[a[i]].add(new Edge(b[i],c[i]));
		}
	}

	long[][] bfs(int s){
		long[][] L = new long[2][size];
		for(int i=0;i<size;i++){
			L[0][i] = -1;
			L[1][i] = -1;
		}
		L[0][s] = 0;
		ArrayDeque<Integer> Q = new ArrayDeque<Integer>();
		Q.add(s);

		while(!Q.isEmpty()){
			int v = Q.poll();
			for(Edge e:list[v]){
				int w = e.to;
				long c = e.cost;
				if(L[0][w]==-1){
					L[0][w] = L[0][v] + c;
					L[1][w] = v;
					Q.add(w);
				}
			}
		}
		return L;
	}
	long[] bfs2(int[] d,int s){
		long[] L = new long[size];
		for(int i=0;i<size;i++){
			L[i] = -1;
		}
		int p = 0;
		L[s] = 0;
		d[s] = p;
		p++;
		ArrayDeque<Integer> Q = new ArrayDeque<Integer>();
		Q.add(s);

		while(!Q.isEmpty()){
			int v = Q.poll();
			for(Edge e:list[v]){
				int w = e.to;
				long c = e.cost;
				if(L[w]==-1){
					d[w] = p;
					p++;
					L[w] = L[v] + c;
					Q.add(w);
				}
			}
		}
		return L;
	}

	int[] isTwoColor(){
		int[] L = new int[size];
		for(int i=0;i<size;i++){
			L[i] = -1;
		}
		L[0] = 0;
		ArrayDeque<Integer> Q = new ArrayDeque<Integer>();
		Q.add(0);

		while(!Q.isEmpty()){
			int v = Q.poll();
			for(Edge e:list[v]){
				int w = e.to;
				if(L[w]==-1){
					L[w] = 1-L[v];
					Q.add(w);
				}else{
					if(L[v]+L[w]!=1){
						L[0] = -2;
					}
				}
			}
		}
		return L;
	}

	long[] dijkstra(int s){
		long[] L = new long[size];
		for(int i=0;i<size;i++){
			L[i] = -1;
		}
		int[] v = new int[size];
		L[s] = 0;
		PriorityQueue<LongIntPair> Q = new PriorityQueue<LongIntPair>(new LongIntSampleComparator());
		Q.add(new LongIntPair(0,s));

		while(!Q.isEmpty()){

			LongIntPair C = Q.poll();

			if(v[C.b]==0){
				L[C.b] = C.a;
				v[C.b] = 1;
				for(Edge D:list[C.b]) {
					if(L[D.to]==-1||L[D.to]>L[C.b]+D.cost) {
						L[D.to]=L[C.b]+D.cost;
						Q.add(new LongIntPair(L[C.b]+D.cost,D.to));
					}

				}
			}
		}
		return L;
	}

	ArrayList<Graph> makeapart(){
		ArrayList<Graph> ans = new ArrayList<Graph>();
		boolean[] b = new boolean[size];
		int[] num = new int[size];
		for(int i=0;i<size;i++){
			if(b[i])continue;
			int sz = 0;
			ArrayList<Integer> l = new ArrayList<Integer>();
			ArrayDeque<Integer> Q = new ArrayDeque<Integer>();
			Q.add(i);
			b[i] = true;
			while(!Q.isEmpty()){
				int v = Q.poll();
				num[v] = sz;
				sz++;
				l.add(v);
				for(Edge e:list[v]){
					if(!b[e.to]){
						Q.add(e.to);
						b[e.to] = true;
					}
				}
			}
			Graph H = new Graph(sz);
			for(int e:l){
				for(Edge E:list[e]){
					H.addWeightedEdge(num[e],num[E.to],E.cost);
				}
			}
			ans.add(H);

		}
		return ans;
	}

	long[] bellmanFord(int s) {
		long inf = 1000000000;
		inf *= inf;
		long[] d = new long[size];
		boolean[] n = new boolean[size];
		d[s] = 0;
		for(int i=1;i<size;i++){
			d[i] = inf;
			d[i] *= d[i];
		}
		for(int i=0;i<size-1;i++){
			for(int j=0;j<size;j++){
				for(Edge E:list[j]){
					if(d[j]!=inf&&d[E.to]>d[j]+E.cost){
						d[E.to]=d[j]+E.cost;
					}
				}
			}
		}
		for(int i=0;i<size;i++){
			for(int j=0;j<size;j++){
				for(Edge e:list[j]){
					if(d[j]==inf) continue;
					if(d[e.to]>d[j]+e.cost) {
						d[e.to]=d[j]+e.cost;
						n[e.to] = true;
					}
					if(n[j])n[e.to] = true;
				}
			}
		}
		for(int i=0;i<size;i++) {
			if(n[i])d[i] = inf;
		}
		return d;
	}

	long[][] WarshallFloyd(long[][] a){
		int n = a.length;
		long[][] ans = new long[n][n];
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				ans[i][j] = a[i][j]==0?(long)1e16:a[i][j];
				if(i==j)ans[i][j]=0;
			}
		}
		for(int k=0;k<n;k++) {
			for(int i=0;i<n;i++) {
				for(int j=0;j<n;j++) {
					ans[i][j] = Math.min(ans[i][j],ans[i][k]+ans[k][j]);
				}
			}
		}
		return ans;
	}
	long[] maxtra(int s,long l){
		long[] L = new long[size];
		for(int i=0;i<size;i++){
			L[i] = -1;
		}
		int[] v = new int[size];
		L[s] = -1;

		PriorityQueue<Pair> Q = new PriorityQueue<Pair>(new SampleComparator());
		Q.add(new Pair(l,s));

		while(!Q.isEmpty()){

			Pair C = Q.poll();
			if(v[(int)C.b]==0){
				L[(int)C.b] = C.a;
				v[(int) C.b] = 1;
				for(Edge D:list[(int) C.b])Q.add(new Pair(Math.max(L[(int)C.b],D.cost),D.to));
			}
		}

		return L;
	}
	long[] mintra(int s){
		long[] L = new long[size];
		for(int i=0;i<size;i++){
			L[i] = -1;
		}
		int[] v = new int[size];
		L[s] = s;

		PriorityQueue<Pair> Q = new PriorityQueue<Pair>(new SampleComparator().reversed());
		Q.add(new Pair(s,s));

		while(!Q.isEmpty()){

			Pair C = Q.poll();
			if(v[(int)C.b]==0){
				L[(int)C.b] = C.a;
				v[(int) C.b] = 1;
				for(Edge D:list[(int) C.b])Q.add(new Pair(Math.min(L[(int)C.b],D.cost),D.to));
			}
		}

		return L;
	}
	long Kruskal(){
		long r = 0;
		for(int i=0;i<size;i++) {
			for(Edge e:list[i]) {
				Edges.add(new LinkEdge(e.cost,i,e.to));
			}
		}
		UnionFindTree UF = new UnionFindTree(size);
		for(LinkEdge e:Edges){
			if(e.a>=0&&e.b>=0) {
				if(!UF.same(e.a,e.b)){
					r += e.L;
					UF.unite(e.a,e.b);
				}
			}
		}
		return r;
	}

	ArrayList<Integer> Kahntsort(){

		ArrayList<Integer> ans = new ArrayList<Integer>();
		PriorityQueue<Integer> q = new PriorityQueue<Integer>();
		int[] in = new int[size];
		for(int i=0;i<size;i++) {
			for(Edge e:list[i])in[e.to]++;
		}
		for(int i=0;i<size;i++) {
			if(in[i]==0)q.add(i);
		}
		while(!q.isEmpty()) {
			int v = q.poll();
			ans.add(v);
			for(Edge e:list[v]) {
				in[e.to]--;
				if(in[e.to]==0)q.add(e.to);
			}
		}
		for(int i=0;i<size;i++) {
			if(in[i]>0)return new ArrayList<Integer>();
		}
		return ans;
	}

	RootedTree dfsTree(int i) {
		int[] u = new int[size];
		RootedTree r = new RootedTree(size);
		dfsTree(i,u,r);
		return r;

	}

	private void dfsTree(int i, int[] u, RootedTree r) {
		u[i] = 1;
		for(Edge e:list[i]) {
			if(u[e.to]==0) {
				r.list[i].add(e);
				u[e.to] = 1;
				dfsTree(e.to,u,r);
			}
		}

	}
}

class Tree extends Graph{

	public Tree(int N) {
		super(N);
	}

	long[] tyokkei(){
		long[][] a = bfs(0);

		System.out.println();
		int md = -1;
		long m = 0;
		for(int i=0;i<size;i++){
			if(m<a[0][i]){
				m = a[0][i];
				md = i;
			}
		}

		long[][] b = bfs(md);
		int md2 = -1;
		long m2 = 0;
		for(int i=0;i<size;i++){
			if(m2<b[0][i]){
				m2 = b[0][i];
				md2 = i;
			}
		}
		long[] r = {m2,md,md2};
		return r;
	}

}

class RootedTree extends Graph{
	RootedTree(int N){
		super(N);
	}
}
class LinkEdge{
	long L;
	int a ;
	int b;
	LinkEdge(long l,int A,int B){
		L = l;
		a = A;
		b = B;
	}
	public boolean equals(Object o){
		LinkEdge O = (LinkEdge) o;
		return O.a==this.a&&O.b==this.b&&O.L==this.L;
	}

	public int hashCode(){
		return Objects.hash(L,a,b);
	}
}

class Edge{
	int to;
	long cost;

	Edge(int a,long b){
		to = a;
		cost = b;
	}
}
class LinkEdgeComparator implements Comparator<LinkEdge>{
	public int compare(LinkEdge P, LinkEdge Q) {
		long t = P.L-Q.L;
		if(t==0){
			if(P.a>Q.a){
				return 1;
			}else{
				return P.b>Q.b?1:-1;

			}
		}
		return t>=0?1:-1;
	}
}

class Triplet{
	long a;
	long b;
	long c;
	Triplet(long p,long q,long r){
		a = p;
		b = q;
		c = r;
	}
	public boolean equals(Object o){
		Triplet O = (Triplet) o;
		return O.a==this.a&&O.b==this.b&&O.c==this.c?true:false;

	}

	public int hashCode(){
		return Objects.hash(a,b,c);
	}
}

class TripletComparator implements Comparator<Triplet>{
	public int compare(Triplet P, Triplet Q) {
		long t = P.a-Q.a;
		if(t==0){
			long tt = P.b-Q.b;
			if(tt==0) {
				if(P.c>Q.c) {
					return 1;
				}else if(P.c<Q.c){
					return -1;
				}else {
					return 0;
				}
			}
			return tt>0?1:-1;
		}
		return t>=0?1:-1;
	}
}
class Pair{
	long a;
	long b;

	Pair(long p,long q){
		this.a = p;
		this.b = q;
	}

	public boolean equals(Object o){
		Pair O = (Pair) o;
		return O.a==this.a&&O.b==this.b;
	}

	public int hashCode(){
		return Objects.hash(a,b);
	}
}

class SampleComparator implements Comparator<Pair>{
	public int compare(Pair P, Pair Q) {
		long t = P.a-Q.a;
		if(t==0){
			return P.b>=Q.b?1:-1;

		}
		return t>=0?1:-1;
	}
}

class LongIntPair{
	long a;
	int b;

	LongIntPair(long p,int q){
		this.a = p;
		this.b = q;
	}

	public boolean equals(Object o){
		Pair O = (Pair) o;
		return O.a==this.a&&O.b==this.b;

	}

	public int hashCode(){
		return Objects.hash(a,b);
	}
}

class LongIntSampleComparator implements Comparator<LongIntPair>{
	public int compare(LongIntPair P, LongIntPair Q) {
		long t = P.a-Q.a;
		if(t==0){
			if(P.b>Q.b){
				return 1;
			}else{
				return -1;
			}
		}
		return t>=0?1:-1;
	}
}

class IntIntPair{
	int a;
	int b;

	IntIntPair(int p,int q){
		this.a = p;
		this.b = q;
	}

	public boolean equals(Object o){
		Pair O = (Pair) o;
		return O.a==this.a&&O.b==this.b;

	}

	public int hashCode(){
		return Objects.hash(a,b);
	}
}

class IntIntSampleComparator implements Comparator<IntIntPair>{
	public int compare(IntIntPair P, IntIntPair Q) {
		int t = P.a-Q.a;
		if(t==0){
			return P.b-Q.b;
		}
		return t;
	}
}

class DoublePair{
	double a;
	double b;

	DoublePair(double p,double q){
		this.a = p;
		this.b = q;
	}

	public boolean equals(Object o){
		Pair O = (Pair) o;
		return O.a==this.a&&O.b==this.b;

	}

	public int hashCode(){
		return Objects.hash(a,b);
	}
}

class DDSampleComparator implements Comparator<DoublePair>{
	public int compare(DoublePair P, DoublePair Q) {
		return P.b-Q.b>=0?1:-1;
	}
}

class DoubleTriplet{
	double a;
	double b;
	double c;

	DoubleTriplet(double p,double q,double r){
		this.a = p;
		this.b = q;
		this.c = r;
	}

	public boolean equals(Object o){
		DoubleTriplet O = (DoubleTriplet) o;
		return O.a==this.a&&O.b==this.b&&O.c==this.c;

	}

	public int hashCode(){
		return Objects.hash(a,b,c);
	}
}

class FastScanner {
    private final java.io.InputStream in = System.in;
    private final byte[] b = new byte[1024];
    private int p = 0;
    private int bl = 0;
    private boolean hNB() {
        if (p<bl) {
            return true;
        }else{
            p = 0;
            try {
                bl = in.read(b);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (bl<=0) {
                return false;
            }
        }
        return true;
    }
    private int rB() { if (hNB()) return b[p++]; else return -1;}
    private static boolean iPC(int c) { return 33 <= c && c <= 126;}
    private void sU() { while(hNB() && !iPC(b[p])) p++;}
    public boolean hN() { sU(); return hNB();}
    public String next() {
        if (!hN()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = rB();
        while(iPC(b)) {
            sb.appendCodePoint(b);
            b = rB();
        }
        return sb.toString();
    }
    public char nextChar() {
    	return next().charAt(0);
    }
    public long nextLong() {
        if (!hN()) throw new NoSuchElementException();
        long n = 0;
        boolean m = false;
        int b = rB();
        if (b=='-') {
            m=true;
            b=rB();
        }
        if (b<'0'||'9'<b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0'<=b&&b<='9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1||!iPC(b)){
                return (m?-n:n);
            }else{
                throw new NumberFormatException();
            }
            b = rB();
        }
    }
    public int nextInt() {
        if (!hN()) throw new NoSuchElementException();
        long n = 0;
        boolean m = false;
        int b = rB();
        if (b == '-') {
            m = true;
            b = rB();
        }
        if (b<'0'||'9'<b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0'<=b&&b<='9') {
                n *= 10;
                n += b-'0';
            }else if(b==-1||!iPC(b)){
                return (int) (m?-n:n);
            }else{
                throw new NumberFormatException();
            }
            b = rB();
        }
    }
    public int[] nextInts(int n) {
    	int[] a = new int[n];
    	for(int i=0;i<n;i++) {
    		a[i] = nextInt();
    	}
    	return a;
    }
    public long[] nextLongs(int n) {
    	long[] a = new long[n];
    	for(int i=0;i<n;i++) {
    		a[i] = nextLong();
    	}
    	return a;
    }
    public int[][] nextIntses(int n,int m){
    	int[][] a = new int[n][m];
    	for(int i=0;i<n;i++) {
    		for(int j=0;j<m;j++) {
    			a[i][j] = nextInt();
    		}
    	}
    	return a;
    }
}

class Mathplus{
	int mod = 1000000007;
	long[] fac;
	long[] revfac;
	long[][] comb;
	long[] pow;
	long[] revpow;
	boolean isBuild = false;
	boolean isBuildc = false;
	boolean isBuildp = false;
	int mindex = -1;
	int maxdex = -1;

	int color(int[][] diff,int N) {

		int[] val = new int[1<<N];
		val[0] = 1;
		for(int i=0;i<(1<<N);i++) {
			for(int j=0;j<N;j++) {
				if(contains(i,j)) {
					if(val[bitremove(i,j)]==1) {
						boolean b = true;
						for(int k=0;k<N;k++) {
							if(contains(i,k)&&diff[j][k]==1) {
								b = false;
							}
						}
						if(b)val[i] = 1;
					}
					break;
				}
			}
		}
		int[] dp = new int[1<<N];
		Arrays.fill(dp,mod);;
		dp[0] = 0;
		for(int i=0;i<(1<<N);i++) {
			for(int j=i;j>0;j=(j-1)&i) {
				if(val[j]==1)dp[i]=Math.min(dp[i],dp[i^j]+1);
			}
		}
		return dp[(1<<N)-1];
	}

	public DoubleTriplet Line(double x1,double y1,double x2,double y2) {
		double a = y1-y2;
		double b = x2-x1;
		double c = x1*y2-x2*y1;
		return new DoubleTriplet(a,b,c);
	}
	public double putx(DoubleTriplet T,double x) {
		return -(T.a*x+T.c)/T.b;
	}
	public double puty(DoubleTriplet T,double y) {
		return -(T.b*y+T.c)/T.a;
	}
	public double DistanceofPointandLine(DoublePair P,Triplet T) {
		return Math.abs(P.a*T.a+P.b*T.b+T.c) / Math.sqrt(T.a*T.a+T.b*T.b);
	}
	public boolean cross(long ax, long ay, long bx, long by, long cx, long cy, long dx, long dy) {
		 long ta = (cx - dx) * (ay - cy) + (cy - dy) * (cx - ax);
		 long tb = (cx - dx) * (by - cy) + (cy - dy) * (cx - bx);
		 long tc = (ax - bx) * (cy - ay) + (ay - by) * (ax - cx);
		 long td = (ax - bx) * (dy - ay) + (ay - by) * (ax - dx);
		 return((tc>=0&&td<=0)||(tc<=0&&td>=0))&&((ta>=0&&tb<=0)||(ta<=0&&tb>=0));
	}
	public boolean dcross(double ax, double ay, double bx, double by, double cx, double cy, double dx, double dy) {
		 double ta = (cx - dx) * (ay - cy) + (cy - dy) * (cx - ax);
		 double tb = (cx - dx) * (by - cy) + (cy - dy) * (cx - bx);
		 double tc = (ax - bx) * (cy - ay) + (ay - by) * (ax - cx);
		 double td = (ax - bx) * (dy - ay) + (ay - by) * (ax - dx);
		 return((tc>=0&&td<=0)||(tc<=0&&td>=0))&&((ta>=0&&tb<=0)||(ta<=0&&tb>=0));
	}

	void buildFac(){
		fac = new long[10000003];
		revfac = new long[10000003];
		fac[0] = 1;
		for(int i=1;i<=10000002;i++){
			fac[i] = (fac[i-1] * i)%mod;
		}
		revfac[10000002] = rev(fac[10000002])%mod;
		for(int i=10000001;i>=0;i--) {
			revfac[i] = (revfac[i+1] * (i+1))%mod;
		}
		isBuild = true;
	}
	public long[] buildrui(int[] a) {
		int n = a.length;
		long[] ans = new long[n];
		ans[0] = a[0];
		for(int i=1;i<n;i++) {
			ans[i] = ans[i-1] + a[i];
		}
		return ans;
	}
	public long[][] buildrui(int[][] a) {
		int n = a.length;
		int m = a[0].length;
		long[][] ans = new long[n][m];
		for(int i=1;i<n;i++) {
			for(int j=1;j<m;j++) {
				ans[i][j] = a[i][j];
			}
		}
		for(int i=1;i<n;i++) {
			for(int j=1;j<m;j++) {
				ans[i][j] += ans[i][j-1] + ans[i-1][j] - ans[i-1][j-1];
			}
		}
		return ans;
	}
	long divroundup(long n,long d) {
		if(n==0)return 0;
		return (n-1)/d+1;
	}
	public long sigma(long i) {
		return i*(i+1)/2;
	}
	public int digit(long i) {
		int ans = 1;
		while(i>=10) {
			i /= 10;
			ans++;
		}
		return ans;

	}
	public int popcount(int i) {
		int ans = 0;
		while(i>0) {
			ans += i%2;
			i /= 2;
		}
		return ans;
	}
	public boolean contains(int S,int i) {return (S>>i&1)==1;}
	public int bitremove(int S,int i) {return S&(~(1<<i));}
	public int bitadd(int S,int i) {return S|(1<<i);}
	public boolean isSubSet(int S,int T) {return (S-T)==(S^T);}
	public boolean isDisjoint(int S,int T) {return (S+T)==(S^T);}
	public int isBigger(int[] d, int i) {
		int ok = d.length;
		int ng = -1;
		while(Math.abs(ok-ng)>1) {
			int mid = (ok+ng)/2;
			if(d[mid]>i) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}
	public int isSmaller(int[] d, int i) {
		int ok = -1;
		int ng = d.length;
		while(Math.abs(ok-ng)>1) {
			int mid = (ok+ng)/2;
			if(d[mid]<i) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}
	public int isBigger(long[] d, long i) {
		int ok = d.length;
		int ng = -1;
		while(Math.abs(ok-ng)>1) {
			int mid = (ok+ng)/2;
			if(d[mid]>i) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}
	public int isSmaller(long[] d, long i) {
		int ok = -1;
		int ng = d.length;
		while(Math.abs(ok-ng)>1) {
			int mid = (ok+ng)/2;
			if(d[mid]<i) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}
	public int isBigger(ArrayList<Long> d, long i) {
		int ok = d.size();
		int ng = -1;
		while(Math.abs(ok-ng)>1) {
			int mid = (ok+ng)/2;
			if(d.get(mid)>i) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}
	public int isSmaller(ArrayList<Long> d, long i) {
		int ok = -1;
		int ng = d.size();
		while(Math.abs(ok-ng)>1) {
			int mid = (ok+ng)/2;
			if(d.get(mid)<i) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}
	public HashSet<Integer> primetable(int m) {
		HashSet<Integer> pt = new HashSet<Integer>();
		for(int i=2;i<=m;i++) {
			boolean b = true;
			for(int d:pt) {
				if(i%d==0) {
					b = false;
					break;
				}
			}
			if(b) {
				pt.add(i);
			}
		}
		return pt;
	}
	public ArrayList<Integer> primetablearray(int m) {
		ArrayList<Integer> al = new ArrayList<Integer>();
		Queue<Integer> q = new ArrayDeque<Integer>();
		for(int i=2;i<=m;i++) {
			q.add(i);

		}
		boolean[] b = new boolean[m+1];
		while(!q.isEmpty()) {
			int e = q.poll();
			if(!b[e]) {
				al.add(e);
				for(int j=1;e*j<=1000000;j++) {
					b[e*j] = true;
				}
			}
		}
		return al;
	}
	public HashMap<Integer,Integer> hipPush(ArrayList<Integer> l){
		HashMap<Integer,Integer> r = new HashMap<Integer,Integer>();
		TreeSet<Integer> s = new TreeSet<Integer>();
		for(int e:l)s.add(e);
		int p = 0;
		for(int e:s) {
			r.put(e,p);
			p++;
		}
		return r;
	}
	public TreeMap<Integer,Integer> thipPush(ArrayList<Integer> l){
		TreeMap<Integer,Integer> r = new TreeMap<Integer,Integer>();
		Collections.sort(l);
		int b = -(mod+9393);
		int p = 0;
		for(int e:l) {
			if(b!=e) {
				r.put(e,p);
				p++;
			}
			b=e;
		}
		return r;
	}

	long max(long[] a){
		long M = 0;
		for(int i=0;i<a.length;i++){
			if(M<a[i]){
				M =a[i];
				maxdex = i;
			}
		}
		return M;
	}
	int max(int[] a){
		int M = 0;
		for(int i=0;i<a.length;i++){
			if(M<a[i]){
				M =a[i];
				maxdex = i;
			}
		}
		return M;
	}
	long min(long[] a){
		long m = Long.MAX_VALUE;
		for(int i=0;i<a.length;i++){
			if(m>a[i]){
				m =a[i];
				mindex = i;
			}
		}
		return m;
	}
	int min(int[] a){
		int m = Integer.MAX_VALUE;
		for(int i=0;i<a.length;i++){
			if(m>a[i]){
				m =a[i];
				mindex = i;
			}
		}
		return m;
	}
	long sum(long[] a){
		long s = 0;
		for(int i=0;i<a.length;i++)s += a[i];
		return s;
	}
	long sum(int[] a){
		long s = 0;
		for(int i=0;i<a.length;i++)s += a[i];
		return s;
	}
	long gcd(long a, long b){
		a = Math.abs(a);
		b = Math.abs(b);
		if(a==0)return b;
		if(b==0)return a;
		if(a%b==0) return b;
		else return gcd(b,a%b);
	}
	int igcd(int a, int b) {
		if(a%b==0) return b;
		else return igcd(b,a%b);
	}
	long lcm(long a, long b) {return a / gcd(a,b) * b;}
	public long perm(int a,int num) {
		if(!isBuild)buildFac();
		return fac[a]*(rev(fac[a-num]))%mod;
	}
	void buildComb(int N) {
		comb = new long[N+1][N+1];
		comb[0][0] = 1;
		for(int i=1;i<=N;i++) {
			comb[i][0] = 1;
			for(int j=1;j<N;j++) {
				comb[i][j] = comb[i-1][j-1]+comb[i-1][j];
				if(comb[i][j]>mod)comb[i][j]-=mod;
			}
			comb[i][i] = 1;
		}
	}
	public long comb(int a,int num){
		if(a-num<0)return 0;
		if(num<0)return 0;
		if(!isBuild)buildFac();
		return fac[a] * ((revfac[num]*revfac[a-num])%mod)%mod;
	}
	long mulchoose(int n,int k) {
		if(k==0) return 1;
		return comb(n+k-1,k);
	}
	long rev(long l) {return pow(l,mod-2);}

	void buildpow(int l,int i) {
		pow = new long[i+1];
		pow[0] = 1;
		for(int j=1;j<=i;j++) {
			pow[j] = pow[j-1]*l;
			if(pow[j]>mod)pow[j] %= mod;
		}
	}
	void buildrevpow(int l,int i) {
		revpow = new long[i+1];
		revpow[0] = 1;
		for(int j=1;j<=i;j++) {
			revpow[j] = revpow[j-1]*l;
			if(revpow[j]>mod) revpow[j] %= mod;
		}
	}
	long pow(long l, long i) {
		if(i==0)return 1;
		else{
			if(i%2==0){
				long val = pow(l,i/2);
				return val * val % mod;
			}
			else return pow(l,i-1) * l % mod;
		}
	}
}


import javafx.util.Pair;

import java.io.*;
import java.util.*;
import static java.lang.Math.*;

public class Main implements Runnable
{
    boolean multiple = false;
    long MOD;

    @SuppressWarnings({"Duplicates", "ConstantConditions"})
    void solve() throws Exception
    {
        int k = sc.nextInt();
        long tar = 0;
        long[][] arr = new long[k][];
        long[] sum = new long[k];
        HashMap<Long, Pair<Integer, Integer>> map = new HashMap<>();
        for (int i = 0; i < k; i++)
        {
            int ni = sc.nextInt();
            arr[i] = new long[ni];
            for (int j = 0; j < ni; j++)
            {
                sum[i] += (arr[i][j] = sc.nextInt());
                map.put(arr[i][j], new Pair<>(i, j));
            }
            tar += sum[i];
        }
        if (tar % k != 0) { System.out.println("No"); return; }
        tar /= k;
        works = new HashMap<>();
        for (int i = 0; i < k; i++)
        {
            outer: for (int j = 0; j < arr[i].length; j++)
            {
                long val = arr[i][j];
                long want = tar - sum[i] + val;
                if (!map.containsKey(want)) continue;
//                ArrayList<pli> list = new ArrayList<>();
                int key = 1 << i;
                int next = map.get(want).getKey();
//                int prev = i;
                HashSet<Integer> seen = new HashSet<>();
                seen.add(i);
                while (true)
                {
                    if (seen.contains(next))
                    {
                        if (next == i && want == arr[i][j])
                            works.put(key, (((long) i) << 32) + ((long) j));
                        break;
                    }
//                    list.add(new pli(want, prev));
                    val = arr[next][map.get(want).getValue()];
                    want = tar - sum[next] + val;
                    if (!map.containsKey(want)) continue outer;
                    key |= 1 << next;
//                    prev = next;
                    seen.add(next);
                    next = map.get(want).getKey();
                }
            }
        }
//        dp.put(0, new ArrayList<>());
        dp = new long[1 << k];
        done = new boolean[1 << k];
        yes = new boolean[1 << k];
        yes[0] = done[0] = true;
        long ans = r((1 << k) - 1);
        long[] val = new long[k];
        int[] pos = new int[k];
        if (!yes[(1 << k) - 1]) System.out.println("No");
        else
        {
//            System.out.println(ans);
//            System.out.println(map);
            System.out.println("Yes");
            while (ans >> 32 != 0)
            {
                long p = works.get((int)(ans >> 32));
                int i = (int)(p >> 32), j = (int)(p & ((1L<<32)-1));
                long VAL = arr[i][j];
                long want = tar - sum[i] + VAL;
                int key = 1 << i;
                int next = map.get(want).getKey();
                int prev = i;
                while (true)
                {
                    if (next == i)
                    {
                        val[map.get(want).getKey()] = want;
                        pos[map.get(want).getKey()] = prev + 1;
                        if (want == arr[i][j])
                            works.put(key, (((long)i)<<32) + ((long)j));
                        break;
                    }
                    val[map.get(want).getKey()] = want;
                    pos[map.get(want).getKey()] = prev + 1;
                    VAL = arr[next][map.get(want).getValue()];
                    want = tar - sum[next] + VAL;
                    key |= 1 << next;
                    prev = next;
                    next = map.get(want).getKey();
                }

                ans = dp[(int)(ans & ((1L << 32)- 1))];
            }
            for (int i = 0; i < k; i++)
                System.out.println(val[i] + " " + pos[i]);
        }
    }

    HashMap<Integer, Long> works;
    long[] dp;
    boolean[] done, yes;

    long r(int mask)
    {
        if (done[mask]) return dp[mask];
        done[mask] = true;
        for (int s = mask; s != 0; s = (s-1) & mask)
            if (works.keySet().contains(s))
            {
                int tempMask = mask;
                for (int i = 0; i < 16; i++)
                    if ((s & (1 << i)) != 0)
                        tempMask ^= 1 << i;
                r(tempMask);
                if (yes[tempMask])
                {
                    yes[mask] = true;
                    return dp[mask] = (((long)s) << 32) + tempMask;
                }
            }
        return 0;
    }

    class pii { int f, s; pii(int k, int v) { f = k; s = v; } }
    class pli { long f; int s; pli(long k, int v) { f = k; s = v; } public String toString() { return "(" + f + ", " + s + ")"; } }
    StringBuilder ANS = new StringBuilder();
    void p(Object s) { ANS.append(s); } void p(double s) {ANS.append(s); } void p(long s) {ANS.append(s); } void p(char s) {ANS.append(s); }
    void pl(Object s) { ANS.append(s); ANS.append('\n'); } void pl(double s) { ANS.append(s); ANS.append('\n'); } void pl(long s) { ANS.append(s); ANS.append('\n'); } void pl(char s) { ANS.append(s); ANS.append('\n'); } void pl() { ANS.append(('\n')); }
    /*I/O, and other boilerplate*/ @Override public void run() { try { in = new BufferedReader(new InputStreamReader(System.in));out = new PrintWriter(System.out);sc = new FastScanner(in);if (multiple) { int q = sc.nextInt();for (int i = 0; i < q; i++) solve(); } else solve(); System.out.print(ANS); } catch (Throwable uncaught) { Main.uncaught = uncaught; } finally { out.close(); }} public static void main(String[] args) throws Throwable{ Thread thread = new Thread(null, new Main(), "", (1 << 26));thread.start();thread.join();if (Main.uncaught != null) {throw Main.uncaught;} } static Throwable uncaught; BufferedReader in; FastScanner sc; PrintWriter out; } class FastScanner { BufferedReader in; StringTokenizer st; public FastScanner(BufferedReader in) {this.in = in;}public String nextToken() throws Exception { while (st == null || !st.hasMoreTokens()) { st = new StringTokenizer(in.readLine()); }return st.nextToken(); }public int nextInt() throws Exception { return Integer.parseInt(nextToken()); }public long nextLong() throws Exception { return Long.parseLong(nextToken()); }public double nextDouble() throws Exception { return Double.parseDouble(nextToken()); }
}


import java.io.*;
import java.util.*;
import java.math.*;
import java.lang.*;

import static java.lang.Math.*;

public class Main implements Runnable
{
	static class InputReader
	{
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;
		private BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

		public InputReader(InputStream stream)
		{
			this.stream = stream;
		}

		public int read()
		{
			if (numChars==-1)
				throw new InputMismatchException();

			if (curChar >= numChars)
			{
				curChar = 0;
				try
				{
					numChars = stream.read(buf);
				}
				catch (IOException e)
				{
					throw new InputMismatchException();
				}

				if(numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public String nextLine()
		{
			String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
		}
		public int nextInt()
		{
			int c = read();

			while(isSpaceChar(c))
				c = read();

			int sgn = 1;

			if (c == '-')
			{
				sgn = -1;
				c = read();
			}

			int res = 0;
			do
			{
				if(c<'0'||c>'9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));

			return res * sgn;
		}

		public long nextLong()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			long res = 0;

			do
			{
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));
				return res * sgn;
		}

		public double nextDouble()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			double res = 0;
			while (!isSpaceChar(c) && c != '.')
			{
				if (c == 'e' || c == 'E')
					return res * Math.pow(10, nextInt());
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			if (c == '.')
			{
				c = read();
				double m = 1;
				while (!isSpaceChar(c))
				{
					if (c == 'e' || c == 'E')
						return res * Math.pow(10, nextInt());
					if (c < '0' || c > '9')
						throw new InputMismatchException();
					m /= 10;
					res += (c - '0') * m;
					c = read();
				}
			}
			return res * sgn;
		}

		public String readString()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do
			{
				res.appendCodePoint(c);
				c = read();
			}
			while (!isSpaceChar(c));

			return res.toString();
		}

		public boolean isSpaceChar(int c)
		{
			if (filter != null)
				return filter.isSpaceChar(c);
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public String next()
		{
			return readString();
		}

		public interface SpaceCharFilter
		{
			public boolean isSpaceChar(int ch);
		}
	}

	public static void main(String args[]) throws Exception
	{
		new Thread(null, new Main(),"Main",1<<26).start();
	}
    int findLSB(long n)
    {
        long value=-n&n;
        return map.get(value);
    }
	void findMaxClique(long mask,int size)
    {
        if(mask==0)
        {
            if(size>maxClique)
                maxClique=size;
            return;
        }
        while(mask>0)
        {
            if(Long.bitCount(mask)+size<=maxClique)
                return;
            int lsb=findLSB(mask);
            mask=mask^((long)1<<lsb);
            findMaxClique(mask&edges[lsb],size+1);
        }
    }
    long edges[];
    HashMap<Long,Integer> map=new HashMap<>();
    int maxClique;
	public void run()
	{
		InputReader sc= new InputReader(System.in);
		PrintWriter w= new PrintWriter(System.out);
        long value=1;
        for(int i=0;i<45;i++)
        {
            map.put(value,i);
            value*=2;
        }
        int n=sc.nextInt();
	    int k=sc.nextInt();
        edges=new long[n];
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                long connect=sc.nextLong();
                if(j>i&&connect==1)
                    edges[i]|=(connect<<j);
            }
        }
        findMaxClique(((long)1<<n)-1,0);
        //w.print(maxClique);
        double size=(double)maxClique;
        double perCastle=(double)k/size;
        double ans=perCastle*perCastle*(size*(size-1))/2;
        w.print(ans);
		w.close();
	}
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.IOException;
import java.util.StringTokenizer;
/*
 * @author Tnascimento
 */

public class MaeDosDragoes {
	// public static StringTokenizer tokenizer;
	// public static BufferedReader reader;
	public static PrintWriter saida = new PrintWriter(System.out, false);
	// public static String proximo() {
	// 	while (tokenizer == null || !tokenizer.hasMoreElements()) {
	// 		try {
	// 			tokenizer = new StringTokenizer(reader.readLine());
	// 		} catch (RuntimeException e) {
	// 			e.printStackTrace();
	// 		}
	// 	}
	// 	return tokenizer.nextToken();
	// }

	public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(Reader in) {
            br = new BufferedReader(in);
        }

        public FastScanner() {
            this(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }
    }

    public static void main(String[] args) {
		FastScanner fastScanner = new FastScanner();
        int proximoInt = fastScanner.nextInt();
        double proximoDouble = fastScanner.nextInt();
        long[] graph = new long[proximoInt];
        for(Integer i = 0; i < proximoInt; i++) {
            for(Integer j =0; j < proximoInt; j++) {
                Integer val = fastScanner.nextInt();
                if (val.equals(1) || i.equals(j)) {
				 graph[i] |= 1L << j;
				}
            }
        }

        int szLeft = proximoInt/2;
        int szRight = proximoInt - szLeft;

        int[] dp = new int[1 << szLeft];
        int maxMask = 1 << szLeft;

        for(int mask = 1; mask <maxMask; mask++) {
            int curMask = mask;

            for(int j = 0; j < szLeft; j++) {
                if (((1 << j) & mask) > 0) {
                    curMask &= graph[j + szRight] >> szRight;
                    dp[mask] = Math.max(dp[mask], dp[mask ^ (1 << j)]);
                }
            }
            if (mask == curMask) {
                dp[mask] = Math.max(dp[mask],Integer.bitCount(mask));
            }
        }
        int ans = 0;
        int rmaxMask = 1 << szRight;
        for(int mask = 0; mask < rmaxMask; mask++) {
            int curMask = mask;
            int oMask = maxMask -1;
            for(int j = 0; j < szRight; j++) {
                if (((1 << j) & mask) > 0) {
                    curMask &= (graph[j] & (rmaxMask-1));
                    oMask &= graph[j] >> szRight;
                }
            }
            if (curMask != mask) continue;
            ans = Math.max(ans, Integer.bitCount(mask) + dp[oMask]);
        }
        proximoDouble/=ans;
        saida.println(proximoDouble * proximoDouble * (ans * (ans-1))/2);
        saida.flush();
    }
}


import java.util.*;
import java.io.*;
public class code839E
{
    public static void main(String[] args) throws Exception{
        BufferedReader bff=new BufferedReader(new InputStreamReader(System.in));
        PrintWriter wff=new PrintWriter(System.out);
        String[] st=bff.readLine().split(" ");
        int V=Integer.parseInt(st[0]);
        int K=Integer.parseInt(st[1]);
        BronKerbosch bk=new BronKerbosch(V);
        for(int i=0;i<V;i++){
            st=bff.readLine().split(" ");
            for(int j=0;j<V;j++){
                if(st[j].equals("1")){
                    bk.anadir(i,j);
                }
            }
        }
        long num=bk.numeroCamarilla();
        wff.printf("%.12f\n", num * (num - 1.0) / 2 * K / num * K / num);
        wff.flush();
    }

static class BronKerbosch {
    int V;
    long[] neig;
    Random random = new Random();
    long maxClique;

    public BronKerbosch(int v){
        V=v;
        neig=new long[V];
    }

    public void anadir(int a,int b){
        long aux=1;
        neig[a] |= aux << (long)b;
    }

    public long numeroCamarilla(){
        long numero = Long.bitCount(bronKerbosch());
        return numero;
    }

    public long bronKerbosch() {
        maxClique = 0;
        bronKerbosch2(0, (1L << V) - 1, 0);
        return maxClique;
    }

    public void bronKerbosch2(long r, long p, long x) {
        if (Long.bitCount(maxClique) >= Long.bitCount(r | p | x)) return;
        long px = p | x;
        if (px == 0) {
            if (Long.bitCount(maxClique) < Long.bitCount(r)) {
                maxClique = r;
            }
            return;
        }
        int cnt = Long.bitCount(px);
        int choice = random.nextInt(cnt);
        int u;
        for (int i = 0; ; i++) {
            if ((px >>> i & 1) != 0 && choice-- == 0) {
                u = i;
                break;
            }
        }

        long ne = p & ~neig[u];
        for (int v = 0; v < V; v++){
            if ((ne >>> v & 1) != 0) {
                bronKerbosch2(r | 1L << v, p & neig[v], x & neig[v]);
                p &= ~(1L << v);
                x |= 1L << v;
            }
        }
    }

}

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Random;
import java.io.IOException;
import java.io.Reader;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author tanzaku
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        MyInput in = new MyInput(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskE {
        int n;
        int k;
        long[] neigibor;
        Random random = new Random();
        long maxClique;

        public void solve(int testNumber, MyInput in, PrintWriter out) {
            n = in.nextInt();
            k = in.nextInt();
            neigibor = new long[n];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    neigibor[i] |= in.nextLong() << j;
                }
            }
            long maxClique = bronKerbosch();
            long a = Long.bitCount(maxClique);
            dump(a);
            out.printf("%.12f\n", a * (a - 1.0) / 2 * k / a * k / a);
        }

        static void dump(Object... o) {
            System.err.println(Arrays.deepToString(o));
        }

        long bronKerbosch() {
            maxClique = 0;
            bronKerbosch2(0, (1L << n) - 1, 0);
            return maxClique;
        }

        void bronKerbosch2(long r, long p, long x) {
            if (Long.bitCount(maxClique) >= Long.bitCount(r | p | x)) return;
            long px = p | x;
            if (px == 0) {
                if (Long.bitCount(maxClique) < Long.bitCount(r)) {
                    maxClique = r;
                }
                return;
            }
            int cnt = Long.bitCount(px);
            int choice = random.nextInt(cnt);
            int u;
            for (int i = 0; ; i++) {
                if ((px >>> i & 1) != 0 && choice-- == 0) {
                    u = i;
                    break;
                }
            }
//        dump(r, p, x, u, neigibor);
            long ne = p & ~neigibor[u];
            for (int v = 0; v < n; v++)
                if ((ne >>> v & 1) != 0) {
                    bronKerbosch2(r | 1L << v, p & neigibor[v], x & neigibor[v]);
                    p &= ~(1L << v);
                    x |= 1L << v;
                }
        }

    }

    static class MyInput {
        private final BufferedReader in;
        private static int pos;
        private static int readLen;
        private static final char[] buffer = new char[1024 * 8];
        private static char[] str = new char[500 * 8 * 2];
        private static boolean[] isDigit = new boolean[256];
        private static boolean[] isSpace = new boolean[256];
        private static boolean[] isLineSep = new boolean[256];

        static {
            for (int i = 0; i < 10; i++) {
                isDigit['0' + i] = true;
            }
            isDigit['-'] = true;
            isSpace[' '] = isSpace['\r'] = isSpace['\n'] = isSpace['\t'] = true;
            isLineSep['\r'] = isLineSep['\n'] = true;
        }

        public MyInput(InputStream is) {
            in = new BufferedReader(new InputStreamReader(is));
        }

        public int read() {
            if (pos >= readLen) {
                pos = 0;
                try {
                    readLen = in.read(buffer);
                } catch (IOException e) {
                    throw new RuntimeException();
                }
                if (readLen <= 0) {
                    throw new MyInput.EndOfFileRuntimeException();
                }
            }
            return buffer[pos++];
        }

        public int nextInt() {
            int len = 0;
            str[len++] = nextChar();
            len = reads(len, isSpace);
            int i = 0;
            int ret = 0;
            if (str[0] == '-') {
                i = 1;
            }
            for (; i < len; i++) ret = ret * 10 + str[i] - '0';
            if (str[0] == '-') {
                ret = -ret;
            }
            return ret;
        }

        public long nextLong() {
            int len = 0;
            str[len++] = nextChar();
            len = reads(len, isSpace);
            int i = 0;
            long ret = 0;
            if (str[0] == '-') {
                i = 1;
            }
            for (; i < len; i++) ret = ret * 10 + str[i] - '0';
            if (str[0] == '-') {
                ret = -ret;
            }
            return ret;
        }

        public char nextChar() {
            while (true) {
                final int c = read();
                if (!isSpace[c]) {
                    return (char) c;
                }
            }
        }

        int reads(int len, boolean[] accept) {
            try {
                while (true) {
                    final int c = read();
                    if (accept[c]) {
                        break;
                    }
                    if (str.length == len) {
                        char[] rep = new char[str.length * 3 / 2];
                        System.arraycopy(str, 0, rep, 0, str.length);
                        str = rep;
                    }
                    str[len++] = (char) c;
                }
            } catch (MyInput.EndOfFileRuntimeException e) {
            }
            return len;
        }

        static class EndOfFileRuntimeException extends RuntimeException {
        }

    }
}


//package round428;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E2 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";
//	String INPUT = "";

	void solve()
	{
		int n = ni(), K = ni();
		long[] g = new long[n];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < n;j++){
				g[i] |= nl()<<j;
			}
			g[i] |= 1L<<i;
		}

		// (K/M)^2*M(M-1)/2
		// K^2*(M-1)/2M
		int mc = solveMaximumClique(g);
		out.printf("%.14f\n", (double)K*K*(mc-1)/2/mc);
	}

	public static int solveMaximumClique(long[] g)
	{
		int n = g.length;
		int h = n/2;
		int[] dp = new int[1<<n-h];
		for(int i = 0;i < 1<<h;i++){
			long cover = (1L<<n)-1;
			for(int j = 0;j < h;j++){
				if(i<<~j<0)cover &= g[j];
			}
			if((cover&i) == i){
				dp[(int)(cover>>>h)] = Math.max(dp[(int)(cover>>>h)], Integer.bitCount(i));
			}
		}
		for(int i = 0;i < n-h;i++){
			for(int j = 0;j < 1<<n-h;j++){
				if(j<<~i>=0){
					dp[j] = Math.max(dp[j], dp[j|1<<i]);
				}
			}
		}

		int ret = 0;
		for(int i = 0;i < 1<<n-h;i++){
			long cover = (1L<<n)-1;
			for(int j = 0;j < n-h;j++){
				if(i<<~j<0)cover &= g[j+h];
			}
			if((cover&(long)i<<h) == (long)i<<h){
				ret = Math.max(ret, Integer.bitCount(i) + dp[i]);
			}
		}
		return ret;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E2().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.IOException;
import java.util.StringTokenizer;
/*
 * @author Tnascimento
 */

public class MaeDosDragoes {
	public static PrintWriter saida = new PrintWriter(System.out, false);
	public static class Escanear {
        BufferedReader reader;
        StringTokenizer tokenizer;
		public Escanear() {
            this(new InputStreamReader(System.in));
        }
		public Escanear(Reader in) {
            reader = new BufferedReader(in);
        }
        String proximo() {
            if (tokenizer == null || !tokenizer.hasMoreElements()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return tokenizer.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(proximo());
        }
    }

    public static void main(String[] args) {
		Escanear fastScanner = new Escanear();
        int proximoInt = fastScanner.nextInt();
        double proximoDouble = fastScanner.nextInt();
        long[] graph = new long[proximoInt];
        for(Integer i = 0; i < proximoInt; i++) {
            for(Integer j =0; j < proximoInt; j++) {
                Integer val = fastScanner.nextInt();
                if (val.equals(1) || i.equals(j)) {
				 graph[i] |= 1L << j;
				}
            }
        }

        int szLeft = proximoInt/2;
        int szRight = proximoInt - szLeft;

        int[] dp = new int[1 << szLeft];
        int maxMask = 1 << szLeft;

        for(int mask = 1; mask <maxMask; mask++) {
            int curMask = mask;

            for(int j = 0; j < szLeft; j++) {
                if (((1 << j) & mask) > 0) {
                    curMask &= graph[j + szRight] >> szRight;
                    dp[mask] = Math.max(dp[mask], dp[mask ^ (1 << j)]);
                }
            }
            if (mask == curMask) {
                dp[mask] = Math.max(dp[mask],Integer.bitCount(mask));
            }
        }
        int ans = 0;
        int rmaxMask = 1 << szRight;
        for(int mask = 0; mask < rmaxMask; mask++) {
            int curMask = mask;
            int oMask = maxMask -1;
            for(int j = 0; j < szRight; j++) {
                if (((1 << j) & mask) > 0) {
                    curMask &= (graph[j] & (rmaxMask-1));
                    oMask &= graph[j] >> szRight;
                }
            }
            if (curMask != mask) continue;
            ans = Math.max(ans, Integer.bitCount(mask) + dp[oMask]);
        }
        proximoDouble/=ans;
        saida.println(proximoDouble * proximoDouble * (ans * (ans-1))/2);
        saida.flush();
    }
}


import java.util.*;
import java.io.*;
/*
 * Heart beats fast
 * 		Colors and promises
 * 			How to be brave
 * 				How can I love when I am afraid...
 */
public class Main
{
	public static void main(String[]args) throws Exception
	{
			int n=ni();
			double ke=ni();
			boolean[][]a=new boolean[n][n];
			for(int i=0; i<n; i++)
				for(int j=0; j<n; j++)
					a[i][j]=ni()==0;
			int left=n/2;
			int[]ldp=new int[1<<left];
			int[]rdp=new int[1<<(n-left)];
			int[]pow=new int[25];
			pow[0]=1;
			for(int i=1; i<25; i++)
				pow[i]=pow[i-1]<<1;
			for(int i=0; i<pow[left]; i++)
				ou:for(int j=0; j<left; j++)
					if((i>>j)%2==0)
					{
						int te=i;
						for(int k=0; te>0; k++,te>>=1)
							if(a[j][k]&&(te&1)!=0)
							{
								ldp[i+pow[j]]=max(ldp[i+pow[j]],ldp[i]);
								continue ou;
							}
						ldp[i+pow[j]]=max(ldp[i+pow[j]],ldp[i]+1);
					}
			int right=n-left;
			for(int i=0; i<pow[right]; i++)
				ou:for(int j=0; j<right; j++)
					if((i>>j)%2==0)
					{
						int lul=j+left;
						int te=i;
						for(int k=left; te>0; k++,te>>=1)
							if(a[lul][k]&&(te&1)!=0)
							{
								rdp[i+pow[j]]=max(rdp[i+pow[j]],rdp[i]);
								continue ou;
							}
						rdp[i+pow[j]]=max(rdp[i+pow[j]],rdp[i]+1);
					}
			int maxi=0;
			for(int i=0; i<pow[left]; i++)
			{
				int lol=0;
				int te=i;
				for(int j=0; te>0; j++,te>>=1)
					if((te&1)!=0)
						for(int k=0; k<right; k++)
							if(a[j][k+left])
								lol|=pow[k];
				maxi=max(maxi,ldp[i]+rdp[pow[right]-1-lol]);
			}
			pr((ke*ke*(maxi-1))/(2*maxi));
		System.out.println(output);
	}
	///////////////////////////////////////////
	///////////////////////////////////////////
	///template from here
//	static final int mod=998_244_353;
	static final int mod=1000_000_007;
	static final double eps=1e-7;
	static final long inf=1000_000_000_000_000_000L;
	static class pair
	{
		int a,b;
		pair(){}
		pair(int c,int d){a=c;b=d;}
		@Override
		public int hashCode()
		{
			return (a+" "+b).hashCode();
		}
		public boolean equals(Object c)
		{
			return (a==(((pair)c).a)&&b==(((pair)c).b));
		}
	}
	public static void sort(int[][]a)
	{
		Arrays.sort(a, new Comparator<int[]>()
				{
			public int compare(int[]a,int[]b)
			{
				if(a[0]>b[0])
					return 1;
				if(a[0]<b[0])
					return -1;
				return 0;
			}
				});
	}
	static interface combiner
	{
		public int combine(int a, int b);
	}
	static void pr(Object a){output.append(a+"\n");}
	static void pr(){output.append("\n");}
	static void p(Object a){output.append(a);}
	static void pra(int[]a){for(int i:a)output.append(i+" ");output.append("\n");}
	static void pra(long[]a){for(long i:a)output.append(i+" ");output.append("\n");}
	static void pra(String[]a){for(String i:a)output.append(i+" ");output.append("\n");}
	static void pra(double[]a){for(double i:a)output.append(i+" ");output.append("\n");}
	static void sop(Object a){System.out.println(a);}
	static void flush(){System.out.print(output);output=new StringBuilder();}
	static int ni(){return Integer.parseInt(in.next());}
	static long nl(){return Long.parseLong(in.next());}
	static String ns(){return in.next();}
	static double nd(){return Double.parseDouble(in.next());}
	static int[] nia(int n){int a[]=new int[n];for(int i=0; i<n; i++)a[i]=ni();return a;}
	static int[] pnia(int n){int a[]=new int[n+1];for(int i=1; i<=n; i++)a[i]=ni();return a;}
	static long[] nla(int n){long a[]=new long[n];for(int i=0; i<n; i++)a[i]=nl();return a;}
	static String[] nsa(int n){String a[]=new String[n];for(int i=0; i<n; i++)a[i]=ns();return a;}
	static double[] nda(int n){double a[]=new double[n];for(int i=0; i<n; i++)a[i]=nd();return a;}
	static Reader in=new Reader();
	static StringBuilder output=new StringBuilder();
	static Random rn=new Random();
	static void reverse(int[]a){for(int i=0; i<a.length/2; i++){a[i]^=a[a.length-i-1];a[a.length-i-1]^=a[i];a[i]^=a[a.length-i-1];}}
	static int log2n(long a)
	{
		int te=0;
		while(a>0)
		{
			a>>=1;
			++te;
		}
		return te;
	}
	static class vectorl implements Iterable<Long>
	{
		long a[];
		int size;
		vectorl(){a=new long[10];size=0;}
		vectorl(int n){a=new long[n];size=0;}
		public void add(long b){if(++size==a.length)a=Arrays.copyOf(a, 2*size);a[size-1]=b;}
		public void sort(){Arrays.sort(a, 0, size);}
		public void sort(int l, int r){Arrays.sort(a, l, r);}
		@Override
		public Iterator<Long> iterator() {
			Iterator<Long> hola=new Iterator<Long>()
					{
				int cur=0;
						@Override
						public boolean hasNext() {
							return cur<size;
						}
						@Override
						public Long next() {
							return a[cur++];
						}
					};
			return hola;
		}
	}
	static class vector implements Iterable<Integer>
	{
		int a[],size;
		vector(){a=new int[10];}
		vector(int n){a=new int[n];}
		public void add(int b){if(++size==a.length)a=Arrays.copyOf(a, 2*size);a[size-1]=b;}
		public void sort(){Arrays.sort(a, 0, size);}
		public void sort(int l, int r){Arrays.sort(a, l, r);}
		@Override
		public Iterator<Integer> iterator() {
			Iterator<Integer> hola=new Iterator<Integer>()
					{
				int cur=0;
						@Override
						public boolean hasNext() {
							return cur<size;
						}
						@Override
						public Integer next() {
							return a[cur++];
						}
					};
			return hola;
		}
	}
	static void exit(){System.out.print(output);System.exit(0);}
	static int min(int... a){int min=a[0];for(int i:a)min=Math.min(min, i);return min;}
	static int max(int... a){int max=a[0];for(int i:a)max=Math.max(max, i);return max;}
	static int gcd(int... a){int gcd=a[0];for(int i:a)gcd=gcd(gcd, i);return gcd;}
	static long min(long... a){long min=a[0];for(long i:a)min=Math.min(min, i);return min;}
	static long max(long... a){long max=a[0];for(long i:a)max=Math.max(max, i);return max;}
	static long gcd(long... a){long gcd=a[0];for(long i:a)gcd=gcd(gcd, i);return gcd;}
	static String pr(String a, long b){String c="";while(b>0){if(b%2==1)c=c.concat(a);a=a.concat(a);b>>=1;}return c;}
	static long powm(long a, long b, long mod2){long an=1;long c=a%mod2;while(b>0){if(b%2==1)an=(an*c)%mod2;c=(c*c)%mod2;b>>=1;}return an;}
	static long pow(long a, long b){long an=1;long c=a;while(b>0){if(b%2==1)an*=c;c*=c;b>>=1;}return an;}
	static int gcd(int a, int b){if(b==0)return a;return gcd(b, a%b);}
	static long gcd(long a, long b){if(b==0)return a;return gcd(b, a%b);}
	static class Reader{
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
    }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.IOException;
import java.util.StringTokenizer;
/*
 * @author Tnascimento
 */

public class MaeDosDragoes {
	public static PrintWriter saida = new PrintWriter(System.out, false);
	public static class Escanear {
        BufferedReader reader;
        StringTokenizer tokenizer;
		public Escanear() {
            this(new InputStreamReader(System.in));
        }
		public Escanear(Reader in) {
            reader = new BufferedReader(in);
        }
        String proximo() {
            if (tokenizer == null || !tokenizer.hasMoreElements()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return tokenizer.nextToken();
        }

        int proximoNum() {
            return Integer.parseInt(proximo());
        }
    }
    public static void main(String[] args) {
		Escanear escanear = new Escanear();
		int proximoInt = escanear.proximoNum();
        long[] aux = new long[proximoInt];
        double proximoDouble = escanear.proximoNum();
        for(Integer i = 0; i < proximoInt; i++) {
            for(Integer j =0; j < proximoInt; j++) {
                Integer val = escanear.proximoNum();
                if (val.equals(1) || i.equals(j)) {
				 aux[i] |= 1L << j;
				}
            }
        }
        int esquerda = proximoInt/2;
        int direita = proximoInt - esquerda;
		int maiorMascara = 1 << esquerda;
		int[] depois = new int[1 << esquerda];
		Integer mascara = 1;
		while (mascara < maiorMascara) {
			int mascaraAtual = mascara;

            for(int j = 0; j < esquerda; j++) {
                if (((1 << j) & mascara) > 0) {
                    mascaraAtual &= aux[j + direita] >> direita;
                    depois[mascara] = Math.max(depois[mascara], depois[mascara ^ (1 << j)]);
                }
            }
            if (mascara == mascaraAtual) {
                depois[mascara] = Math.max(depois[mascara],Integer.bitCount(mascara));
			}
			mascara++;
		}
        // for(int mascara = 1; mascara < maiorMascara; mascara++) {
        //     int mascaraAtual = mascara;

        //     for(int j = 0; j < esquerda; j++) {
        //         if (((1 << j) & mascara) > 0) {
        //             mascaraAtual &= aux[j + direita] >> direita;
        //             depois[mascara] = Math.max(depois[mascara], depois[mascara ^ (1 << j)]);
        //         }
        //     }
        //     if (mascara == mascaraAtual) {
        //         depois[mascara] = Math.max(depois[mascara],Integer.bitCount(mascara));
        //     }
        // }
        int auxiliar = 0;
        int mascaraMaxima = 1 << direita;
        for(int masc = 0; masc < mascaraMaxima; masc++) {
            int mascaraCorrente = masc;
            int mascaraValor = maiorMascara -1;
            for(int j = 0; j < direita; j++) {
                if (((1 << j) & masc) > 0) {
                    mascaraCorrente &= (aux[j] & (mascaraMaxima-1));
                    mascaraValor &= aux[j] >> direita;
                }
            }
            if (mascaraCorrente != masc) continue;
            auxiliar = Math.max(auxiliar, Integer.bitCount(masc) + depois[mascaraValor]);
        }
        proximoDouble/=auxiliar;
        saida.println(proximoDouble * proximoDouble * (auxiliar * (auxiliar-1))/2);
        saida.flush();
    }
}


import java.util.*;
public class Main {
	static int a[][],n;
	static boolean isClique[];
	static int maxClique[];
	static void DFS1(int p,int n,int S)
	{
		if(p>n)
		{
			isClique[S]=true;
			return ;
		}
		DFS1(p+1,n,S);
		boolean mark=true;
		for(int i=1;i<p;++i)
			if((S>>(i-1)&1)==1&&a[p][i]==0)
				mark=false;
		if(mark)
			DFS1(p+1,n,1<<(p-1)|S);
	}
	static void DFS2(int p,int n,int m,int S)
	{
		if(p>n)
		{
			int cnt=0;
			for(int i=m;i<=n;++i)
				if((S>>(i-m)&1)==1)
					++cnt;
			maxClique[S]=cnt;
			return ;
		}
		DFS2(p+1,n,m,S);
		boolean mark=true;
		for(int i=m;i<p;++i)
			if((S>>(i-m)&1)==1&&a[p][i]==0)
				mark=false;
		if(mark)
			DFS2(p+1,n,m,1<<(p-m)|S);
	}
	public static void main(String[] args)
	{
		Scanner sc=new Scanner(System.in);
		n=Integer.parseInt(sc.next());
		a=new int [n+10][n+10];
		int cap=Integer.parseInt(sc.next());
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				a[i][j]=Integer.parseInt(sc.next());
		int m=(n+1)>>1;
		isClique=new boolean [1<<m];
		Arrays.fill(isClique,false);
		DFS1(1,m,0);
		maxClique=new int [1<<(n-m)];
		Arrays.fill(maxClique,0);
		DFS2(m+1,n,m+1,0);
		for(int i=1;i<1<<(n-m);++i)
			for(int j=m+1;j<=n;++j)
				if((i>>(j-m-1)&1)==1)
					maxClique[i]=Math.max(maxClique[i],maxClique[i-(1<<(j-m-1))]);
		int ans=0,tmp[]=new int [m+10];
		for(int i=0;i<1<<m;++i)
			if(isClique[i])
			{
				int mask=0,cnt=0;
				for(int j=1;j<=m;++j)
					if((i>>(j-1)&1)==1)
						tmp[++cnt]=j;
				for(int j=m+1;j<=n;++j)
				{
					boolean mark=true;
					for(int k=1;k<=cnt;++k)
						if(a[j][tmp[k]]==0)
							mark=false;
					if(mark)
						mask|=1<<(j-m-1);
				}
				ans=Math.max(ans,cnt+maxClique[mask]);
			}
		System.out.printf("%.9f\n",cap*cap*(ans-1)/2.0/ans);
	}
}