//package cf568d2;
import java.util.*;
public class G {
    static int n,t;
    static int[]a;
    static int[]g;
    static long[][][]dp;
    static final long MOD=1000000007;
    public static void main(String[]args){
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        t=sc.nextInt();
        a=new int[n];
        g=new int[n];
        for(int i=0;i<n;i++) {
            a[i] = sc.nextInt();
            g[i] = sc.nextInt();
        }
        dp=new long[4][1<<(n-1)+1][t+1];
        for(int i=0;i<4;i++)
            for(int j=0;j<1<<(n-1)+1;j++)
                for(int k=0;k<=t;k++)
                    dp[i][j][k]=-1;
        System.out.println(dp(0,0,t));
    }
    private static long dp(int genre,int mask,int time){
        if(time<0)
            return 0;
        if(dp[genre][mask][time]!=-1)
            return dp[genre][mask][time];
        if(time==0)
            return 1;
        dp[genre][mask][time]=0;
        for(int i=0;i<n;i++) {
            if (g[i] != genre && ((1 << i) & mask) == 0)
                dp[genre][mask][time] = (dp[genre][mask][time]+dp(g[i], mask | (1 << i), time - a[i]))%MOD;
        }
        return dp[genre][mask][time];
    }
}


import java.util.*;
import java.io.*;
import java.math.*;
public class Solution{
    public static long mod = 1000000007;
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out);
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int t = Integer.parseInt(st.nextToken());
        int[] d = new int[n];
        int[] g = new int[n];
        for(int i=0;i<n;i++){
            st = new StringTokenizer(br.readLine());
            d[i] = Integer.parseInt(st.nextToken());
            g[i] = Integer.parseInt(st.nextToken())-1;
        }
        long[][] dp = new long[(1<<n)][3];
        for(int i=0;i<n;i++){
            dp[(1<<i)][g[i]] = 1;
        }
        long res = 0;
        for(int i=1;i<(1<<n);i++){
            int k = i;
            int sum = 0;
            for(int j=n-1;j>=0;j--){
                if(k>=(1<<j)){
                    k-=(1<<j);
                    sum += d[j];
                }
                else{
                    for(int r=0;r<3;r++) if(r!=g[j]) dp[i+(1<<j)][g[j]] += dp[i][r];
                    dp[i+(1<<j)][g[j]] %= mod;
                }
            }
            if(sum==t){
                res += dp[i][0] +dp[i][1] +dp[i][2];
                res %= mod;
            }
        }
        out.println(res);
        out.flush();
    }
}

1185_G1. Playlist for Polycarp (easy version)


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;

public class Main {

	static PrintWriter out;
	static InputReader ir;

	static void solve() {
		int n = ir.nextInt();
		int t = ir.nextInt();
		int[][] a = new int[n][];
		for (int i = 0; i < n; i++)
			a[i] = ir.nextIntArray(2);
		long[] f = fact(15);
		long res = 0;
		for (int i = 0; i < 1 << n; i++) {
			int[] ct = new int[4];
			int tot = 0;
			for (int j = 0; j < n; j++) {
				if (((1 << j) & i) != 0) {
					tot += a[j][0];
					ct[a[j][1]]++;
				}
			}
			if (tot != t)
				continue;
			long[][][][] dp = new long[ct[1] + 1][ct[2] + 1][ct[3] + 1][4];
			dp[0][0][0][0] = 1;
			for (int j = 0; j < ct[1] + ct[2] + ct[3]; j++) {
				for (int k = 0; k <= ct[1]; k++) {
					for (int l = 0; l <= ct[2]; l++) {
						if (k + l > j || j - k - l > ct[3])
							continue;
						for (int m = 0; m <= 3; m++) {
							for (int o = 0; o <= 3; o++) {
								if (m == o)
									continue;
								if (o == 1 && k == ct[1])
									continue;
								if (o == 2 && l == ct[2])
									continue;
								if (o == 3 && j - k - l == ct[3])
									continue;

								if (o == 1) {
									dp[k + 1][l][j - k - l][1] = add(dp[k + 1][l][j - k - l][1],
											dp[k][l][j - k - l][m]);
								}
								if (o == 2) {
									dp[k][l + 1][j - k - l][2] = add(dp[k][l + 1][j - k - l][2],
											dp[k][l][j - k - l][m]);
								}
								if (o == 3) {
									dp[k][l][j - k - l + 1][3] = add(dp[k][l][j - k - l + 1][3],
											dp[k][l][j - k - l][m]);
								}

							}
						}
					}
				}
			}
			for (int m = 0; m <= 3; m++)
				res = add(res, mul(mul(f[ct[1]], f[ct[2]]), mul(f[ct[3]], dp[ct[1]][ct[2]][ct[3]][m])));
		}
		out.println(res);
	}

	static long mod = (long) 1e9 + 7;

	static long add(long a, long b) {
		return (a + b) % mod;
	}

	static long sub(long a, long b) {
		long d = a - b;
		while (d < 0)
			d += mod;
		return d;
	}

	static long mul(long a, long b) {
		return a * b % mod;
	}

	static long div(long a, long b) {
		return a * mod_inverse(b) % mod;
	}

	private static long[] fact(int n) {
		long[] ret = new long[n + 1];
		ret[0] = 1 % mod;
		for (int i = 1; i <= n; i++) {
			ret[i] = mul(ret[i - 1], i);
		}
		return ret;
	}

	private static long[] factInv(int n) {
		long[] ret = new long[n + 1];
		ret[0] = 1;
		for (int i = 1; i <= n; i++) {
			ret[i] = div(ret[i - 1], i);
		}
		return ret;
	}

	public static long comb(int n, int m, long[] fact, long[] factInv) {
		long ret = fact[n];
		ret = mul(ret, factInv[m]);
		ret = mul(ret, factInv[n - m]);
		return ret;
	}

	public static long[][] stirling(int n) {
		long[][] ret = new long[n + 1][n + 1];
		ret[0][0] = 1;
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= i; j++)
				ret[i][j] = add(ret[i - 1][j - 1], mul(ret[i - 1][j], j));
		return ret;
	}

	public static long mod_inverse(long a) {
		long[] ret = extgcd(a, mod);
		return add(mod, ret[0] % mod);
	}

	public static long[] extgcd(long a, long b) {
		long[] ret = new long[3];
		ret[2] = _extgcd(a, b, ret);
		return ret;
	}

	private static long _extgcd(long a, long b, long[] x) {
		long g = a;
		x[0] = 1;
		x[1] = 0;
		if (b != 0) {
			g = _extgcd(b, a % b, x);
			long temp = x[0];
			x[0] = x[1];
			x[1] = temp;
			x[1] -= (a / b) * x[0];
		}
		return g;
	}

	static long modpow(long a, long n) {
		long res = 1;
		while (n > 0) {
			if ((n & 1) != 0)
				res = res * a % mod;
			a = a * a % mod;
			n >>= 1;
		}
		return res;
	}

	public static void main(String[] args) {
		ir = new InputReader(System.in);
		out = new PrintWriter(System.out);
		solve();
		out.flush();
	}

	static class InputReader {

		private InputStream in;
		private byte[] buffer = new byte[1024];
		private int curbuf;
		private int lenbuf;

		public InputReader(InputStream in) {
			this.in = in;
			this.curbuf = this.lenbuf = 0;
		}

		public boolean hasNextByte() {
			if (curbuf >= lenbuf) {
				curbuf = 0;
				try {
					lenbuf = in.read(buffer);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (lenbuf <= 0)
					return false;
			}
			return true;
		}

		private int readByte() {
			if (hasNextByte())
				return buffer[curbuf++];
			else
				return -1;
		}

		private boolean isSpaceChar(int c) {
			return !(c >= 33 && c <= 126);
		}

		private void skip() {
			while (hasNextByte() && isSpaceChar(buffer[curbuf]))
				curbuf++;
		}

		public boolean hasNext() {
			skip();
			return hasNextByte();
		}

		public String next() {
			if (!hasNext())
				throw new NoSuchElementException();
			StringBuilder sb = new StringBuilder();
			int b = readByte();
			while (!isSpaceChar(b)) {
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		public int nextInt() {
			if (!hasNext())
				throw new NoSuchElementException();
			int c = readByte();
			while (isSpaceChar(c))
				c = readByte();
			boolean minus = false;
			if (c == '-') {
				minus = true;
				c = readByte();
			}
			int res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res = res * 10 + c - '0';
				c = readByte();
			} while (!isSpaceChar(c));
			return (minus) ? -res : res;
		}

		public long nextLong() {
			if (!hasNext())
				throw new NoSuchElementException();
			int c = readByte();
			while (isSpaceChar(c))
				c = readByte();
			boolean minus = false;
			if (c == '-') {
				minus = true;
				c = readByte();
			}
			long res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res = res * 10 + c - '0';
				c = readByte();
			} while (!isSpaceChar(c));
			return (minus) ? -res : res;
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}

		public int[] nextIntArray(int n) {
			int[] a = new int[n];
			for (int i = 0; i < n; i++)
				a[i] = nextInt();
			return a;
		}

		public long[] nextLongArray(int n) {
			long[] a = new long[n];
			for (int i = 0; i < n; i++)
				a[i] = nextLong();
			return a;
		}

		public char[][] nextCharMap(int n, int m) {
			char[][] map = new char[n][m];
			for (int i = 0; i < n; i++)
				map[i] = next().toCharArray();
			return map;
		}
	}

	static void tr(Object... o) {
		out.println(Arrays.deepToString(o));
	}
}


import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

 public class realfast implements Runnable {
    private static final int INF = (int) 1e9;
    int time[]= new int[15];
     int g[]= new int [15];
    public  void solve() throws IOException
    {
     int n = readInt();
     int t = readInt();

     for(int i=0;i<n;i++)
     {
     	time[i]=readInt();
     	g[i]=readInt();
     }
     long dp[][]= new long [(int)Math.pow(2,n)][4];
     for(int i =0;i<(int)Math.pow(2,n);i++)
     {
      for(int j=0;j<=3;j++)
       dp[i][j]=-1;
     }
     long val = cal(dp,0,0,0,t);
     out.println(val);

    }
    public long cal(long dp[][], int mask , int genre , int t ,int T  )
    {
    	int val = dp.length;

        if(t>T)
        {
         return 0;
        }
    	if(t==T)
    	{
    	 	return 1;
    	}

       if(dp[mask][genre]!=-1)
        return dp[mask][genre];
        dp[mask][genre]=0;
       int i=1;
       int count=0;
       while(i<val)
       {

       	if((i&mask)==0&&g[count]!=genre)
       	{
       	 	dp[mask][genre] = ((dp[mask][genre]%1000000007)+ cal(dp,mask|i,g[count],t+time[count],T)%1000000007)%1000000007;
       	}
       	i=2*i;
       	count++;
       }
       return dp[mask][genre];
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static void main(String[] args) {
        new Thread(null, new realfast(), "", 128 * (1L << 20)).start();
    }

    private static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;
    private BufferedReader reader;
    private StringTokenizer tokenizer;
    private PrintWriter out;

    @Override
    public void run() {
        try {
            if (ONLINE_JUDGE || !new File("input.txt").exists()) {
                reader = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(System.out);
            } else {
                reader = new BufferedReader(new FileReader("input.txt"));
                out = new PrintWriter("output.txt");
            }
            solve();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                // nothing
            }
            out.close();
        }
    }

    private String readString() throws IOException {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }

    @SuppressWarnings("unused")
    private int readInt() throws IOException {
        return Integer.parseInt(readString());
    }

    @SuppressWarnings("unused")
    private long readLong() throws IOException {
        return Long.parseLong(readString());
    }

    @SuppressWarnings("unused")
    private double readDouble() throws IOException {
        return Double.parseDouble(readString());
    }
}
class edge implements Comparable<edge>{
    int u ;
    int v ;
    int val;
    edge(int u1, int v1 , int val1)
    {
       this.u=u1;
       this.v=v1;
       this.val=val1;
    }
    public int compareTo(edge e)
    {
        return this.val-e.val;
    }
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;

public class codeforces {

    public static long cnt = 0;

    public static void f(int g1, int g2, int g3, int last) {
        if (g1 == 0 && g2 == 0 && g3 == 0) cnt++;
        if (g1 > 0 && last != 1) f(g1 - 1, g2, g3, 1);
        if (g2 > 0 && last != 2) f(g1, g2 - 1, g3, 2);
        if (g3 > 0 && last != 3) f(g1, g2, g3 - 1, 3);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader scan = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(scan.readLine());
        int n = Integer.parseInt(st.nextToken());
        int t = Integer.parseInt(st.nextToken());
        int T[] = new int[n];
        int G[] = new int[n];
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(scan.readLine());
            T[i] = Integer.parseInt(st.nextToken());
            G[i] = Integer.parseInt(st.nextToken());
        }
        long ans = 0;
        for (int mask = 1; mask < (1 << n); mask++) {
            int sum = 0;
            int g1 = 0;
            int g2 = 0;
            int g3 = 0;

            for (int i = 0; i < n; i++) {
                if (((1 << i) & mask) > 0) {
                    sum += T[i];
                    if (G[i] == 1) g1++;
                    if (G[i] == 2) g2++;
                    if (G[i] == 3) g3++;
                }
            }
            cnt = 0;
            if (sum == t) f(g1, g2, g3, -1);
            for (long i = 1; i <= g1; i++) cnt *= i;
            for (long i = 1; i <= g2; i++) cnt *= i;
            for (long i = 1; i <= g3; i++) cnt *= i;
            ans += cnt;
        }
        System.out.println(ans % 1000000007);
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

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

    static class G1PlaylistForPolycarpEasyVersion {
        static final int mod = (int) 1e9 + 7;

        public void solve(int testNumber, inputClass sc, PrintWriter out) {
            int n = sc.nextInt();
            int t = sc.nextInt();
            G1PlaylistForPolycarpEasyVersion.Song[] songs = new G1PlaylistForPolycarpEasyVersion.Song[n];
            for (int i = 0; i < n; i++) {
                songs[i] = new G1PlaylistForPolycarpEasyVersion.Song(sc.nextInt(), sc.nextInt());
            }
            long ans = 0;
            for (int mask = 1; mask < (1 << n); mask++) {
                int nb = 0;
                int tot = 0;
                int type1 = 0;
                int type2 = 0;
                int type3 = 0;
                for (int j = 0; j < n; j++) {
                    if (((1 << j) & mask) > 0) {
                        nb++;
                        tot += songs[j].l;
                        if (songs[j].type == 1) {
                            type1++;
                        } else if (songs[j].type == 2) {
                            type2++;
                        } else {
                            type3++;
                        }
                    }
                }

                if (tot == t) {
                    long[][][][][] dp = new long[nb + 1][3][type1 + 1][type2 + 1][type3 + 1];
                    boolean[][][][][] go = new boolean[nb + 1][3][type1 + 1][type2 + 1][type3 + 1];
                    if (type1 > 0) {
                        go[1][0][type1 - 1][type2][type3] = true;
                        dp[1][0][type1 - 1][type2][type3] = type1;
                    }
                    if (type2 > 0) {
                        go[1][1][type1][type2 - 1][type3] = true;
                        dp[1][1][type1][type2 - 1][type3] = type2;
                    }
                    if (type3 > 0) {
                        go[1][2][type1][type2][type3 - 1] = true;
                        dp[1][2][type1][type2][type3 - 1] = type3;
                    }
                    for (int i = 0; i < nb; i++) {
                        for (int m = 0; m < 3; m++) {
                            for (int j = 0; j <= type1; j++) {
                                for (int k = 0; k <= type2; k++) {
                                    for (int l = 0; l <= type3; l++) {
                                        if (go[i][m][j][k][l]) {
                                            if (m == 0) {
                                                if (k > 0) {
                                                    dp[i + 1][1][j][k - 1][l] += dp[i][m][j][k][l] * k;
                                                    dp[i + 1][1][j][k - 1][l] %= mod;
                                                    go[i + 1][1][j][k - 1][l] = true;
                                                }
                                                if (l > 0) {
                                                    dp[i + 1][2][j][k][l - 1] += dp[i][m][j][k][l] * l;
                                                    dp[i + 1][2][j][k][l - 1] %= mod;
                                                    go[i + 1][2][j][k][l - 1] = true;
                                                }
                                            } else if (m == 1) {
                                                if (j > 0) {
                                                    dp[i + 1][0][j - 1][k][l] += dp[i][m][j][k][l] * j;
                                                    dp[i + 1][0][j - 1][k][l] %= mod;
                                                    go[i + 1][0][j - 1][k][l] = true;
                                                }
                                                if (l > 0) {
                                                    dp[i + 1][2][j][k][l - 1] += dp[i][m][j][k][l] * l;
                                                    dp[i + 1][2][j][k][l - 1] %= mod;
                                                    go[i + 1][2][j][k][l - 1] = true;
                                                }
                                            } else {
                                                if (j > 0) {
                                                    dp[i + 1][0][j - 1][k][l] += dp[i][m][j][k][l] * j;
                                                    dp[i + 1][0][j - 1][k][l] %= mod;
                                                    go[i + 1][0][j - 1][k][l] = true;
                                                }
                                                if (k > 0) {
                                                    dp[i + 1][1][j][k - 1][l] += dp[i][m][j][k][l] * k;
                                                    dp[i + 1][1][j][k - 1][l] %= mod;
                                                    go[i + 1][1][j][k - 1][l] = true;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    long toadd = 0;
                    for (int i = 0; i < 3; i++) {
                        toadd += dp[nb][i][0][0][0];
                    }
                    ans += toadd;
                    ans %= (int) 1e9 + 7;
                }
            }
            out.println(ans);
        }

        static class Song {
            int l;
            int type;

            public Song(int x, int y) {
                l = x;
                type = y;
            }

        }

    }

    static class inputClass {
        BufferedReader br;
        StringTokenizer st;

        public inputClass(InputStream in) {

            br = new BufferedReader(new InputStreamReader(in));
        }

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

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

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.IOException;
import java.io.InputStream;

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

    static class G1PlaylistForPolycarpEasyVersion {
        final long mod = 1000000007;
        PrintWriter out;
        InputReader in;
        int n;
        int time;
        int[][] arr;
        long[][][] dp;

        long go(int last, int t, int mask) {
            if (t > time)
                return 0;
            if (t == time) {
                return 1l;
            }
            if (mask == (1 << n) - 1)
                return 0;
            if (dp[last][t][mask] != -1)
                return dp[last][t][mask];
            long cnt = 0;
            int i = 0, j = 0;
            for (i = 0; i < n; i++) {
                if ((mask & (1 << i)) == 0 && arr[i][1] != last) {
                    cnt += go(arr[i][1], t + arr[i][0], mask | (1 << i));
                    cnt %= mod;

                }
            }
            dp[last][t][mask] = cnt;
            return cnt;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            this.out = out;
            this.in = in;
            n = ni();
            time = ni();
            arr = new int[n][2];
            int i = 0;
            for (i = 0; i < n; i++) {
                arr[i][0] = ni();
                arr[i][1] = ni() - 1;
            }
            dp = new long[3][time + 1][1 << n];
            for (i = 0; i < 3; i++) {
                for (int j = 0; j <= time; j++)
                    Arrays.fill(dp[i][j], -1);
            }
            long ans = (((go(0, 0, 0) + go(1, 0, 0)) % mod + go(2, 0, 0)) % mod);
            ans *= modPow(2, mod - 2);
            ans %= mod;
            pn(ans);
        }

        int ni() {
            return in.nextInt();
        }

        void pn(Object o) {
            out.println(o);
        }

        long modPow(long a, long p) {
            long o = 1;
            while (p > 0) {
                if ((p & 1) == 1) o = mul(o, a);
                a = mul(a, a);
                p >>= 1;
            }
            return o;
        }

        long mul(long a, long b) {
            if (a >= mod) a %= mod;
            if (b >= mod) b %= mod;
            a *= b;
            if (a >= mod) a %= mod;
            return a;
        }

    }

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

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

        public int read() {
            if (numChars == -1)
                throw new UnknownError();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new UnknownError();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

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

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

            return res.toString();
        }

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

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

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

    static class G1PlaylistForPolycarpEasyVersion {
        long mod = (long) 1e9 + 7;

        public void solve(int testNumber, InputReader s, PrintWriter w) {
            int n = s.nextInt(), T = s.nextInt();
            int[] t = new int[n + 1];
            int[] g = new int[n + 1];
            int[] f = new int[4];
            for (int i = 1; i <= n; i++) {
                t[i] = s.nextInt();
                g[i] = s.nextInt();
                f[g[i]]++;
            }
            long[] fact = new long[n + 1];
            fact[0] = 1;
            for (int i = 1; i <= n; i++)
                fact[i] = fact[i - 1] * i % mod;
            long[][][][] perm = new long[f[1] + 1][f[2] + 1][f[3] + 1][3 + 1];
            long[][][] sumPerm = new long[f[1] + 1][f[2] + 1][f[3] + 1];
            perm[0][0][0][0] = 1;
            for (int a = 0; a <= f[1]; a++) {
                for (int b = 0; b <= f[2]; b++) {
                    for (int c = 0; c <= f[3]; c++) {
                        if (a - 1 >= 0)
                            perm[a][b][c][1] = (sumPerm[a - 1][b][c] - perm[a - 1][b][c][1] + mod) % mod;
                        if (b - 1 >= 0)
                            perm[a][b][c][2] = (sumPerm[a][b - 1][c] - perm[a][b - 1][c][2] + mod) % mod;
                        if (c - 1 >= 0)
                            perm[a][b][c][3] = (sumPerm[a][b][c - 1] - perm[a][b][c - 1][3] + mod) % mod;
                        for (int i = 0; i <= 3; i++)
                            sumPerm[a][b][c] = (sumPerm[a][b][c] + perm[a][b][c][i]) % mod;
                    }
                }
            }
            long[][][][][] dp = new long[n + 1][f[1] + 1][f[2] + 1][f[3] + 1][T + 1];
            dp[0][0][0][0][0] = 1;
            for (int i = 1; i <= n; i++) {
                for (int a = 0; a <= f[1]; a++) {
                    for (int b = 0; b <= f[2]; b++) {
                        for (int c = 0; c <= f[3]; c++) {
                            for (int j = 0; j <= T; j++) {
                                dp[i][a][b][c][j] = dp[i - 1][a][b][c][j];
                                if (j - t[i] >= 0) {
                                    if (g[i] == 1 && a > 0) {
                                        dp[i][a][b][c][j] = (dp[i][a][b][c][j] + dp[i - 1][a - 1][b][c][j - t[i]]) % mod;
                                    } else if (g[i] == 2 && b > 0) {
                                        dp[i][a][b][c][j] = (dp[i][a][b][c][j] + dp[i - 1][a][b - 1][c][j - t[i]]) % mod;
                                    } else if (g[i] == 3 && c > 0) {
                                        dp[i][a][b][c][j] = (dp[i][a][b][c][j] + dp[i - 1][a][b][c - 1][j - t[i]]) % mod;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            long res = 0;
            for (int a = 0; a <= f[1]; a++)
                for (int b = 0; b <= f[2]; b++)
                    for (int c = 0; c <= f[3]; c++)
                        res = (res + dp[n][a][b][c][T] * sumPerm[a][b][c] % mod * fact[a] % mod * fact[b] % mod * fact[c] % mod) % mod;
            w.println(res);
        }

    }

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

        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 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 boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

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

        }

    }
}


import java.io.*;
import java.util.*;

public class CF1185G2 {
	static final int MD = 1000000007;
	static int[][] solve1(int[] aa, int t, int n) {
		int[][] da = new int[t + 1][n + 1];
		da[0][0] = 1;
		for (int i = 0; i < n; i++) {
			int a = aa[i];
			for (int s = t - 1; s >= 0; s--)
				for (int m = 0; m < n; m++) {
					int x = da[s][m];
					if (x != 0) {
						int s_ = s + a;
						if (s_ <= t)
							da[s_][m + 1] = (da[s_][m + 1] + x) % MD;
					}
				}
		}
		return da;
	}
	static int[][][] solve2(int[] aa, int[] bb, int t, int na, int nb) {
		int[][] da = solve1(aa, t, na);
		int[][][] dab = new int[t + 1][na + 1][nb + 1];
		for (int s = 0; s <= t; s++)
			for (int ma = 0; ma <= na; ma++)
				dab[s][ma][0] = da[s][ma];
		for (int i = 0; i < nb; i++) {
			int b = bb[i];
			for (int s = t - 1; s >= 0; s--)
				for (int ma = 0; ma <= na; ma++)
					for (int mb = 0; mb < nb; mb++) {
						int x = dab[s][ma][mb];
						if (x != 0) {
							int s_ = s + b;
							if (s_ <= t)
								dab[s_][ma][mb + 1] = (dab[s_][ma][mb + 1] + x) % MD;
						}
					}
		}
		return dab;
	}
	static long power(int a, int k) {
		if (k == 0)
			return 1;
		long p = power(a, k / 2);
		p = p * p % MD;
		if (k % 2 == 1)
			p = p * a % MD;
		return p;
	}
	static int[] ff, gg;
	static int ch(int n, int k) {
		return (int) ((long) ff[n] * gg[n - k] % MD * gg[k] % MD);
	}
	static int[][][] init(int n, int na, int nb, int nc) {
		ff = new int[n + 1];
		gg = new int[n + 1];
		for (int i = 0, f = 1; i <= n; i++) {
			ff[i] = f;
			gg[i] = (int) power(f, MD - 2);
			f = (int) ((long) f * (i + 1) % MD);
		}
		int[][][] dp = new int[na + 1][nb + 1][nc + 1];
		for (int ma = 0; ma <= na; ma++)
			for (int mb = 0; mb <= nb; mb++)
				for (int mc = 0; mc <= nc; mc++) {
					int x = (int) ((long) ff[ma + mb + mc] * gg[ma] % MD * gg[mb] % MD * gg[mc] % MD);
					for (int ma_ = ma == 0 ? 0 : 1; ma_ <= ma; ma_++) {
						int cha = ma == 0 ? 1 : ch(ma - 1, ma_ - 1);
						for (int mb_ = mb == 0 ? 0 : 1; mb_ <= mb; mb_++) {
							int chb = mb == 0 ? 1 : ch(mb - 1, mb_ - 1);
							for (int mc_ = mc == 0 ? 0 : 1; mc_ <= mc; mc_++) {
								int chc = mc == 0 ? 1 : ch(mc - 1, mc_ - 1);
								int y = dp[ma_][mb_][mc_];
								if (y == 0)
									continue;
								x = (int) ((x - (long) y * cha % MD * chb % MD * chc) % MD);
							}
						}
					}
					if (x < 0)
						x += MD;
					dp[ma][mb][mc] = x;
				}
		for (int ma = 0; ma <= na; ma++)
			for (int mb = 0; mb <= nb; mb++)
				for (int mc = 0; mc <= nc; mc++)
					dp[ma][mb][mc] = (int) ((long) dp[ma][mb][mc] * ff[ma] % MD * ff[mb] % MD * ff[mc] % MD);
		return dp;
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int t = Integer.parseInt(st.nextToken());
		int[] aa = new int[n];
		int[] bb = new int[n];
		int[] cc = new int[n];
		int na = 0, nb = 0, nc = 0;
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken());
			int g = Integer.parseInt(st.nextToken());
			if (g == 1)
				aa[na++] = a;
			else if (g == 2)
				bb[nb++] = a;
			else
				cc[nc++] = a;
		}
		int[][][] dp = init(n, na, nb, nc);
		int[][][] dab = solve2(aa, bb, t, na, nb);
		int[][] dc = solve1(cc, t, nc);
		int ans = 0;
		for (int tab = 0; tab <= t; tab++) {
			int tc = t - tab;
			for (int ma = 0; ma <= na; ma++)
				for (int mb = 0; mb <= nb; mb++) {
					int xab = dab[tab][ma][mb];
					if (xab == 0)
						continue;
					for (int mc = 0; mc <= nc; mc++) {
						int xc = dc[tc][mc];
						if (xc == 0)
							continue;
						ans = (int) ((ans + (long) xab * xc % MD * dp[ma][mb][mc]) % MD);
					}
				}
		}
		System.out.println(ans);
	}
}


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class G_PlaylistForPolycarp {

	static final int mod = 1000000007;

	static int dp[][];

	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		String[] dat = br.readLine().split(" ");

		int n = Integer.parseInt(dat[0]);
		int T = Integer.parseInt(dat[1]);

		int[] st = new int[n];
		byte[] sg = new byte[n];

		dp = new int[1 << (n + 1)][4];

		for (int j = 0; j < 1 << (n + 1); j++) {
			for (int k = 0; k < 4; k++) {
				dp[j][k] = -1;
			}
		}

		for (int i = 0; i < n; i++) {
			dat = br.readLine().split(" ");
			st[i] = Integer.parseInt(dat[0]);
			sg[i] = Byte.parseByte(dat[1]);
		}

		short visited = 0;

		int count = recur(0, visited, st, sg, T, 0);

		bw.write(count + "\n");

		bw.close();

	}

	private static int recur(int time, short visited, int[] st, byte[] sg, int T, int last) {

		int count = 0;

		if (dp[visited][last] != -1) {
			return dp[visited][last];
		}

		for (int i = 0; i < st.length; i++) {

			if ((visited & (1 << i)) == 0 && sg[i] != last) {

				if (time + st[i] == T) {
					count += 1;
				} else if (time + st[i] < T) {
					short visitedc = (short) (visited | (1 << i));
					count += recur(time + st[i], visitedc, st, sg, T, sg[i]);
					if (count > mod) {
						count = count % mod;
					}
				}

			}

		}

		return dp[visited][last] = count % mod;
	}

}


/*Author: Satyajeet Singh, Delhi Technological University*/
    import java.io.*;
    import java.util.*;
    import java.text.*;
    import java.lang.*;
    import java.math.*;

public class Main{
/*********************************************Constants******************************************/
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static long mod=(long)1e9+7;
    static long mod1=998244353;
    static boolean sieve[];
    static ArrayList<Integer> primes;
    static long factorial[],invFactorial[];
    static HashSet<Pair> graph[];
    static boolean oj = System.getProperty("ONLINE_JUDGE") != null;
/****************************************Solutions Begins***************************************/
    static int n,T,input[],type[];
    static long dp[][];

    static long dfs(int mask,int t){

        if(dp[mask][t]!=-1){
            return dp[mask][t];
        }
        int s=0;
        for(int i=0;i<n;i++){
            if((mask&(1<<i))!=0){
                s+=input[i];
            }
        }
        if(s>T){
            return 0;
        }
        if(s==T){
            dp[mask][t]=1;
            return dp[mask][t];
        }
        long ans=0;
        for(int i=0;i<n;i++){
            if((mask&(1<<i))==0&&type[i]!=t){
                ans=(ans+dfs(mask|(1<<i),type[i]))%mod;
            }
        }
        dp[mask][t]=ans;
        return dp[mask][t];
    }
    public static void main (String[] args) throws Exception {
        String st[]=nl();
        n=pi(st[0]);
        T=pi(st[1]);
        input=new int[n];
        type=new int[n];
        for(int i=0;i<n;i++){
            st=nl();
            input[i]=pi(st[0]);
            type[i]=pi(st[1]);
        }
        dp=new long[1<<n][4];
        for(long arr[]:dp)
            Arrays.fill(arr,-1);
        long ans=dfs(0,0);
       // debug(dp);

        out.println(ans);
/****************************************Solutions Ends**************************************************/
        out.flush();
        out.close();
    }
/****************************************Template Begins************************************************/
    static String[] nl() throws Exception{
        return br.readLine().split(" ");
    }
    static String[] nls() throws Exception{
        return br.readLine().split("");
    }
    static int pi(String str) {
        return Integer.parseInt(str);
    }
    static long pl(String str){
        return Long.parseLong(str);
    }
    static double pd(String str){
        return Double.parseDouble(str);
    }
/***************************************Precision Printing**********************************************/
    static void printPrecision(double d){
        DecimalFormat ft = new DecimalFormat("0.00000000000000000");
        out.println(ft.format(d));
    }
/**************************************Bit Manipulation**************************************************/
    static void printMask(long mask){
        System.out.println(Long.toBinaryString(mask));
    }
    static int countBit(int mask){
        int ans=0;
        while(mask!=0){
            if(mask%2==1){
                ans++;
            }
            mask/=2;
        }
        return ans;
    }
/******************************************Graph*********************************************************/
    static void Makegraph(int n){
        graph=new HashSet[n];
        for(int i=0;i<n;i++){
            graph[i]=new HashSet<>();
        }
    }
    static void addEdge(int a,int b){
        graph[a].add(new Pair(b,1));
    }
    static void addEdge(int a,int b,int c){
        graph[a].add(new Pair(b,c));
    }
/*********************************************PAIR********************************************************/
    static class PairComp implements Comparator<Pair>{
        public int compare(Pair p1,Pair p2){
            return ((p1.u+p1.v)-(p2.u+p2.v));
        }
    }
    static class Pair implements Comparable<Pair> {
        int u;
        int v;
        int index=-1;
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }
        public int hashCode() {
            int hu = (int) (u ^ (u >>> 32));
            int hv = (int) (v ^ (v >>> 32));
            return 31 * hu + hv;
        }
        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return u == other.u && v == other.v;
        }
        public int compareTo(Pair other) {
            if(index!=other.index)
                return Long.compare(index, other.index);
            return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
        }
        public String toString() {
            return "[u=" + u + ", v=" + v + "]";
        }
    }
/******************************************Long Pair*************************************************/
    static class PairCompL implements Comparator<Pairl>{
        public int compare(Pairl p1,Pairl p2){
            if((p1.u+2*p1.v)-(p2.u+2*p2.v)<0){
                return -1;
            }
            else if((p1.u+2*p1.v)-(p2.u+2*p2.v)>0){
                return 1;
            }
            else{
                return 0;
            }
        }
    }
    static class Pairl implements Comparable<Pairl> {
            long u;
            long v;
            int index=-1;
            public Pairl(long u, long v) {
                this.u = u;
                this.v = v;
            }

            public int hashCode() {
                int hu = (int) (u ^ (u >>> 32));
                int hv = (int) (v ^ (v >>> 32));
                return 31 * hu + hv;
            }

            public boolean equals(Object o) {
                Pair other = (Pair) o;
                return u == other.u && v == other.v;
            }

            public int compareTo(Pairl other) {
                if(index!=other.index)
                    return Long.compare(index, other.index);
                return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
            }

            public String toString() {
                return "[u=" + u + ", v=" + v + "]";
            }
        }
/*****************************************DEBUG***********************************************************/
    public static void debug(Object... o) {
        if(!oj)
        System.out.println(Arrays.deepToString(o));
    }
/************************************MODULAR EXPONENTIATION***********************************************/
    static long modulo(long a,long b,long c) {
        long x=1;
        long y=a;
        while(b > 0){
            if(b%2 == 1){
                x=(x*y)%c;
            }
            y = (y*y)%c; // squaring the base
            b /= 2;
        }
        return  x%c;
    }
/********************************************GCD**********************************************************/
    static long gcd(long x, long y)
    {
        if(x==0)
            return y;
        if(y==0)
            return x;
        long r=0, a, b;
        a = (x > y) ? x : y; // a is greater number
        b = (x < y) ? x : y; // b is smaller number
        r = b;
        while(a % b != 0)
        {
            r = a % b;
            a = b;
            b = r;
        }
        return r;
    }
/******************************************SIEVE**********************************************************/
    static void sieveMake(int n){
        sieve=new boolean[n];
        Arrays.fill(sieve,true);
        sieve[0]=false;
        sieve[1]=false;
        for(int i=2;i*i<n;i++){
            if(sieve[i]){
                for(int j=i*i;j<n;j+=i){
                    sieve[j]=false;
                }
            }
        }
        primes=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            if(sieve[i]){
                primes.add(i);
            }
        }
    }
/********************************************End***********************************************************/
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
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;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        G1PlaylistForPolycarpEasyVersion solver = new G1PlaylistForPolycarpEasyVersion();
        solver.solve(1, in, out);
        out.close();
    }

    static class G1PlaylistForPolycarpEasyVersion {
        static ArrayList<Integer> list;
        static int n;
        static int req;
        static int mod = (int) 1e9 + 7;
        static int[] dur;
        static int[] genre;
        static Integer[][][] memo;

        public void solve(int testNumber, Scanner sc, PrintWriter pw) {
            n = sc.nextInt();
            req = sc.nextInt();
            dur = new int[n];
            genre = new int[n];
            list = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                dur[i] = sc.nextInt();
                genre[i] = sc.nextInt();
            }
            int ans = 0;
            memo = new Integer[1 << n][n + 1][4];
            for (int i = 0; i <= n; i++)
                ans += bf(0, 0, 0, i) % mod;
            pw.print(ans % mod);
        }

        private int bf(int idx, int msk, int before, int max) {
            if (idx == max) {
                int sum = 0;
                for (int x : list)
                    sum += x;
                if (sum == req)
                    return 1;
                return 0;
            }
            if (memo[msk][max][before] != null)
                return memo[msk][max][before] % mod;
            int toRet = 0;
            for (int i = 0; i < n; i++) {
                if (genre[i] != before && (msk & 1 << i) == 0) {
                    list.add(dur[i]);
                    toRet += bf(idx + 1, msk | 1 << i, genre[i], max);
                    toRet %= mod;
                    list.remove(list.size() - 1);
                }
            }
            return memo[msk][max][before] = (toRet % mod);
        }

    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(FileReader r) {
            br = new BufferedReader(r);
        }

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

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

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

    }
}


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

public class Solution {

    BufferedReader in;
    PrintWriter out;
    StringTokenizer st;

    int[] x;
    int[] y;
    int n;
    int X, Y;

    int[] d;
    int[][] dist;

    int sqr(int a) {
        return a * a;
    }

    int dist(int X, int Y, int i) {
        return sqr(X - x[i]) + sqr(Y - y[i]);
    }

    int[] dp;
    byte[][] pred;

    int rec(int mask) {
        if (dp[mask] == -1) {
            int res = 1 << 29;
            boolean ok = false;
            for (int i = 0; i < n; ++i)
                if ((mask & (1 << i)) > 0) {
                    ok = true;
                    int mm = mask & ~(1 << i);
                    for (int j = i; j < n; j++)
                        if ((mask & (1 << j)) > 0) {
                            int nmask = mm & ~(1 << j);
                            int a = rec(nmask) + d[i] + d[j] + dist[i][j];
                            if (a < res) {
                                res = a;
                                pred[0][mask] = (byte) (i);
                                pred[1][mask] = (byte) (j);
                            }
                        }
                    break;
                }
            if (!ok)
                res = 0;
            dp[mask] = res;
        }
        return dp[mask];
    }

    void solve() throws IOException {
        X = ni();
        Y = ni();
        n = ni();
        x = new int[n];
        y = new int[n];
        for (int i = 0; i < n; i++) {
            x[i] = ni();
            y[i] = ni();
        }
        d = new int[n];
        dist = new int[n][n];
        for (int i = 0; i < n; ++i)
            d[i] = dist(X, Y, i);
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; j++) {
                dist[i][j] = dist(x[i], y[i], j);
            }
        pred = new byte[2][1 << n];
        dp = new int[1 << n];
        Arrays.fill(dp, -1);
        out.println(rec((1 << n) - 1));
        int a = (1 << n) - 1;
        while (a > 0) {
            if (pred[0][a] != pred[1][a])
                out.print(0 + " " + (pred[0][a] + 1) + " " + (pred[1][a] + 1)
                        + " ");
            else
                out.print(0 + " " + (pred[0][a] + 1) + " ");
            int na = a & ~(1 << pred[0][a]);
            na &= ~(1 << pred[1][a]);
            a = na;
        }
        out.println(0);
    }

    public Solution() throws IOException {
        Locale.setDefault(Locale.US);
        in = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        in.close();
        out.close();
    }

    String ns() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }

    int ni() throws IOException {
        return Integer.valueOf(ns());
    }

    long nl() throws IOException {
        return Long.valueOf(ns());
    }

    double nd() throws IOException {
        return Double.valueOf(ns());
    }

    public static void main(String[] args) throws IOException {
        new Solution();
    }
}


import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;

/**
 * Created by 11815 on 2017/7/1.
 */
public class Main {
    private static int[] x = new int[26], y = new int[26], dp = new int[1<<24], pre = new int[1<<24];
    private static int dis(int i, int j) {
        return (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int x0 = in.nextInt(), y0 = in.nextInt(), n = in.nextInt();
        for (int i = 0; i < n; i++) {
            x[i] = in.nextInt();
            y[i] = in.nextInt();
        }
        x[n] = x0;
        y[n] = y0;
        int[][] gra = new int[26][26];
        for (int i = 0; i < n + 1; i++) {
            for (int j = i+1; j < n+1; j++) {
                gra[i][j] = gra[j][i] = dis(i,j);
            }
        }
        Arrays.fill(dp, -1);
        dp[0] = 0;
        for (int i = 0; i < 1 << n; i++) {
            if (dp[i] != -1) {
                for (int j = 0; j < n; j++) {
                    if (((1<<j)&i) == 0) {
                        int t = i | (1<<j), tmp = dp[i] + 2*gra[j][n];
                        if (dp[t] == -1 || dp[t] > tmp) {
                            dp[t] = tmp;
                            pre[t] = i;
                        }
                        for (int k = 0; k < n; k++) {
                            if ((t&(1<<k)) == 0) {
                                int t2 = t | (1<<k), tmp2 = dp[i] + gra[n][j] + gra[j][k] + gra[k][n];
                                if (dp[t2] == -1 || dp[t2] > tmp2) {
                                    dp[t2] = tmp2;
                                    pre[t2] = i;
                                }
                            }
                        }
                        break;
                    }
                }
            }
        }
        int end = (1<<n)-1, cnt = 0;
        int[] ans = new int[60];
        System.out.println(dp[end]);
        while (end != 0) {
            int pr = pre[end];
            int tem = pr^end;
            int a = 0, b = 0;
            for (int i = 0; i < n; i++) {
                if (((1<<i)&tem)!=0) {
                    b=a;
                    a=i+1;
                }
            }
            ans[cnt++] = 0;
            ans[cnt++] = a;
            if (b>0) {
                ans[cnt++] = b;
            }
            end = pr;
        }
        ans[cnt++] = 0;
        for (int i = cnt-1; i >= 0; i--) {
            System.out.print(ans[i] + " ");
        }
        System.out.print("\n");
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/** Created by huhansan on 2017/10/9. */
public class CF_8C implements Runnable {
  int[] step = new int[1 << 24]; //每个状态所需要的步数
  int[] steplast = new int[1 << 24]; //当前状态上一个
  int n;
  int vs[] = new int[24];
  int vd[][] = new int[24][24];
  int x_bag, y_bag;
  int x[] = new int[24], y[] = new int[24];
  /** */
  private void solve() throws IOException {
    x_bag = nextInt();
    y_bag = nextInt();
    n = nextInt();
    for (int i = 0; i < n; i++) {
      x[i] = nextInt();
      y[i] = nextInt();
    }

    //计算所有物品单取的全值和 任意两件物品一起取的权值
    for (int i = 0; i < n; i++) {
      vs[i] = 2 * ((x[i] - x_bag) * (x[i] - x_bag) + (y[i] - y_bag) * (y[i] - y_bag));
    }
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        vd[i][j] =
            (x[i] - x_bag) * (x[i] - x_bag)
                + (y[i] - y_bag) * (y[i] - y_bag)
                + (x[j] - x_bag) * (x[j] - x_bag)
                + (y[j] - y_bag) * (y[j] - y_bag)
                + (x[i] - x[j]) * (x[i] - x[j])
                + (y[i] - y[j]) * (y[i] - y[j]);
      }
    }

    //记录达到每一个状态所需的最小步数和最后一次取得物品
    for (int i = 1; i < 1 << n; i++) {
      int j, k = 0, l, m, lastState;
      for (j = 1; (i & j) == 0 && j < 1 << n; j <<= 1) {
        k++;
      }
      lastState = i & (~j);
      step[i] = step[lastState] + vs[k];
      steplast[i] = lastState;
      m = k;
      for (l = j << 1; l < 1 << n; l <<= 1) {
        m++;
        if ((lastState & l) != 0) {
          if (step[i] > step[lastState & (~l)] + vd[k][m]) {
            step[i] = step[lastState & (~l)] + vd[k][m];
            steplast[i] = lastState & (~l);
          }
        }
      }
      //      System.out.println(steplast[i]+"---"+i+"---"+step[i]);
    }
    writer.println(step[(1 << n) - 1]);
    int i = (1 << n) - 1;
    writer.print("0 ");
    while (i != 0) {
      for (int j = 1, m = 1; j <= i; j <<= 1, m++) {
        if ((j & (i ^ steplast[i])) != 0) {
          writer.print(m + " ");
        }
      }
      writer.print("0 ");
      i = steplast[i];
    }
  }

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

  BufferedReader reader;
  StringTokenizer tokenizer;
  PrintWriter writer;

  public void run() {
    try {
      reader = new BufferedReader(new InputStreamReader(System.in));
      tokenizer = null;
      writer = new PrintWriter(System.out);
      solve();
      reader.close();
      writer.close();
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }
  }

  int nextInt() throws IOException {
    return Integer.parseInt(nextToken());
  }

  long nextLong() throws IOException {
    return Long.parseLong(nextToken());
  }

  double nextDouble() throws IOException {
    return Double.parseDouble(nextToken());
  }

  String nextToken() throws IOException {
    while (tokenizer == null || !tokenizer.hasMoreTokens()) {
      tokenizer = new StringTokenizer(reader.readLine());
    }
    return tokenizer.nextToken();
  }
}


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

public class Main  implements Runnable {
//public static final String FileName = "test";
StreamTokenizer ST;
PrintWriter out;
BufferedReader br;
Scanner in;
static final int inf = 1000000000+10;

int nextInt() throws IOException{
    ST.nextToken();
    return (int)ST.nval;
}
long nextLong() throws IOException{
    ST.nextToken();
    return (long)ST.nval;
}
String next() throws IOException{
    ST.nextToken();
    return ST.sval;
}
double nextD() throws IOException{
    ST.nextToken();
    return ST.nval;
}
public static void main(String[] args) throws IOException {
   new Thread(new Main()).start();
//	new Main().run();
}

public void run()  {
    try {
    	br = new BufferedReader(new InputStreamReader(System.in));
    	out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    	//br = new BufferedReader(new FileReader(new File(FileName+".in")));
    	//out = new PrintWriter(new BufferedWriter(new FileWriter(FileName+".out")));
    	//in = new Scanner(br);
        ST = new StreamTokenizer(br);
        solve();
        out.close();
        //in.close();
        br.close();
    }
    catch (IOException e) {
    	e.printStackTrace();
    	throw new IllegalStateException(e);
    }
}

public void solve() throws IOException {
	int[] x = new int[32];
	int[] y = new int[32];
	x[0] = nextInt();
	y[0] = nextInt();
	int n = nextInt();
	for (int i=1; i<=n; i++) {
		x[i] = nextInt();
		y[i] = nextInt();
	}
	n++;
	int[][] a = new int[n][n];
	int[][] b = new int[n-1][n-1];
	for (int i=0; i<n; i++)
		for (int j=0; j<n; j++)
			a[i][j] = (x[i]-x[j])*(x[i]-x[j])+ (y[i]-y[j])*(y[i]-y[j]);
	for (int i=1; i<n; i++)
		for (int j=1; j<n; j++)
			if (i!=j) b[i-1][j-1] = a[0][i]+a[i][j]+a[j][0]; else b[i-1][j-1] = 2*a[0][i];
	n--;

	int sz = 1<<n;
	int[] d = new int[sz];
	int[] p = new int[sz];
	d[1] = 0;
	for (int msk=1; msk<sz; msk++) {
		int j = 0;
		while ((msk&(1<<j))==0) j++;
		int t = inf;
		for (int i=0; i<n; i++)
			if ((msk&(1<<i))>0)
			if (t>d[msk^((1<<i)|(1<<j))]+b[i][j]) {
				t = d[msk^((1<<i)|(1<<j))]+b[i][j];
				p[msk] = i*n+j;
			}
		d[msk] = t;

	}
	out.println(d[sz-1]);
	out.print("0 ");
	int t = sz-1;
	while (t>0) {
		int hz = p[t];
		int i = hz/n;
		int j = hz%n;
		if (i!=j) out.print((i+1)+" "+(j+1)+" 0 ");else out.print((i+1)+" 0 ");
		t ^= (1<<i)|(1<<j);
	}

}

}


import java.util.*;
import java.io.*;

public class Main{

    BufferedReader in;
    StringTokenizer str = null;
    PrintWriter out;

    private String next() throws Exception{
    	if (str == null || !str.hasMoreElements())
    	    str = new StringTokenizer(in.readLine());
    	return str.nextToken();
    }

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

    int []x,y;
    int n;
    int []dp, prev;

    public void run() throws Exception{
    	in = new BufferedReader(new InputStreamReader(System.in));
    	out = new PrintWriter(System.out);

    	int xs = nextInt();
    	int ys = nextInt();
    	n = nextInt();
    	x = new int[n];
    	y = new int[n];
    	for(int i=0;i<n;i++){
    		x[i] = nextInt();
    		y[i] = nextInt();
    	}

    	int one[] = new int[n];
    	for(int i=0;i<n;i++){
    		one[i] = dist(xs, ys, x[i], y[i]);
    	}

    	int two[][] = new int[n][n];
    	for(int i=0;i<n;i++){
    		for(int j=i+1;j<n;j++){
    			two[i][j] = two[j][i] = dist(xs, ys, x[i], y[i]) + dist(x[i], y[i], x[j], y[j]) + dist(xs, ys, x[j], y[j]);
    		}
    	}

    	dp = new int[1<<n];
    	Arrays.fill(dp, Integer.MAX_VALUE/2);
    	dp[0] = 0;
    	prev = new int[1<<n];
    	Arrays.fill(prev, -1);

    	for(int mask=1;mask<(1<<n);mask++){
    		int i = 0;
    		while((mask & (1<<i)) == 0) i++;
    		dp[mask] = dp[mask ^ (1<<i)] + 2*one[i];
    		prev[mask] = i+1;
    		for(int j=i+1;j<n;j++){
    			if ((mask & (1<<j)) > 0) {
    				if (dp[mask] > dp[mask ^ (1<<i) ^ (1<<j)] + two[i][j]) {
    					dp[mask] = dp[mask ^ (1<<i) ^ (1<<j)] + two[i][j];
    					prev[mask] = 100 * (i+1) + (j+1);
    				}
    			}
    		}
    	}

    	out.println(dp[(1<<n)-1]);
    	out.print(0 + " ");
    	int cur = (1<<n)-1;
    	int i = 0, j = 0;
    	while(cur > 0) {
    		i = prev[cur]/100;
    		j = prev[cur]%100;

    		if (i > 0) {
    			cur^=1<<(i-1);
    			out.print(i + " ");
    		}

    		if (j > 0) {
    			cur^=1<<(j-1);
    			out.print(j + " ");
    		}

    		out.print(0 + " ");
    	}
    	// if (i == 0 || j == 0) {
    	// 	out.println(0);
    	// }
		out.close();
    }

    private String bit2str(int mask, int n) {
    	String s = "";
    	for(int i=0;i<n;i++){
    		if ((mask & (1<<i)) > 0){
    			s+="1";
    		}else{
    			s+="0";
    		}
    	}
    	while(s.length() < n)
    		s+="0";

    	return new StringBuilder(s).reverse().toString();
    }

    private int dist(int x1, int y1, int x2, int y2) {
    	return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
    }

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


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

// Jonathan
// cpt_fwiffo

public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String[] line = in.readLine().split(" ");
        int Xs = Integer.parseInt(line[0]);
        int Ys = Integer.parseInt(line[1]);
        int n = Integer.parseInt(in.readLine());

        int[][] points = new int[n+1][2];
        points[n][0] = Xs;//set starting point as last point for finding distances
        points[n][1] = Ys;

        for(int i=0; i< n ; i++)
        {
            line = in.readLine().split(" ");
            points[i][0] = Integer.parseInt(line[0]);
            points[i][1] = Integer.parseInt(line[1]);
        }

        int[][] distances = new int[n+1][n+1];
        ComputeDistances(points, distances, n);

        int[] dp = new int[1<<n];
        int[] path = new int[1<<n];
        ComputeLowestPath(dp, path, distances, n);
        OutputLowestAndPath(dp, path, n);

    }

    private static void ComputeLowestPath(int[] dp, int[] path, int[][] distances, int n)
    {
        for(int i = 1; i < 1<<n; i++)
        {
            int j = 0;
            while(true) //find first 1 (LSB)
            {
                if((i&(1<<j))!=0) //check for a bit equal to 1 in location j
                {
                    break;
                }
                j++;
            }

            int pastEntry = i & ~(1<<j); //remove first 1 from i
            path[i] = pastEntry; //set the path we came from to trace later
            int distance = distances[j][n] * 2; //distance from origin to the point being removed, and back
            dp[i] = dp[pastEntry] + distance; //set minimum distance if just this point is added to the collection

            for(int m = j +1; m < n; m++)
            {
                if((i & (1<<m))!=0)
                {
                    int entry = i & ~((1<<j)|(1<<m)); //remove both 1 at position j and 1 at position m from i
                    distance = distances[j][n] + distances[j][m] + distances[m][n]; //calculate round-trip distance to grab 2 points

                    if(dp[i] > dp[entry] + distance) // check if this new option is a better choice.  If it is, update our value and our path.
                    {
                        dp[i] = dp[entry] + distance;
                        path[i] = entry;
                    }
                }
            }

        }
    }

    private static void OutputLowestAndPath(int[] dp, int[] path, int n)
    {

        StringBuilder out = new StringBuilder();
        out.append(dp[(1<<n)-1]);//output min value of traversal
        out.append("\n");
        out.append("0 ");
        int index = (1<<n)-1; //start at our min value
        while(index != 0)
        {
            int j = path[index];
            int k = index ^ j; //find the one or two values that were added at this step
            for(int m = 0; m < n; m++)
            {
                if((k & (1 << m)) != 0)
                {
                    out.append(m+1);
                    out.append(" ");
                }
            }
            out.append("0 ");
            index = j;
        }
        System.out.println(out.toString());
    }

    private static void ComputeDistances(int[][] points, int[][] distances, int n)
    {
        for(int i = 0; i <= n; i++) //calculate distances between all points so that we don't have to compute later
        {
            for(int j=i+1; j<=n; j++)
            {
                int x= points[i][0] - points[j][0];
                int y= points[i][1] - points[j][1];
                distances[i][j] = x*x + y*y;
            }
        }
    }

}


import java.io.*;
import java.util.*;

public class CF8C {
	FastScanner in;
	PrintWriter out;

	int[] x, y;
	int[] av;
	int[][] d = new int[25][25];

	int dist(int v, int u) {
		if (u == v)
			return 0;
		return (d[v][u] == 0 ? d[v][u] = d[u][v] = (x[v] - x[u])
				* (x[v] - x[u]) + (y[v] - y[u]) * (y[v] - y[u]) : d[v][u]);
	}

	void add(int x) {
		av[++av[0]] = x;
	}

	int size() {
		return av[0];
	}

	int get(int i) {
		return av[i + 1];
	}

	int N = 24;
	int[] dp = new int[(1 << N)];
	int[] dpFrom = new int[1 << N];

	void solve() {
		int x1 = in.nextInt();
		int y1 = in.nextInt();
		int n = in.nextInt();

		x = new int[n + 1];
		y = new int[n + 1];
		for (int i = 1; i <= n; i++) {
			x[i] = in.nextInt();
			y[i] = in.nextInt();
		}
		x[0] = x1;
		y[0] = y1;
		Arrays.fill(dp, Integer.MAX_VALUE);
		dp[0] = 0;
		av = new int[n + 1];
		for (int i = 0; i <= n; i++)
			for (int j = 0; j <= n; j++)
				dist(i, j);
		for (int st = 0; st < (1 << n); st++) {
			if (dp[st] == Integer.MAX_VALUE)
				continue;
			av[0] = 0;
			for (int i = 0; i < n; i++)
				if ((st & (1 << i)) == 0)
					add(i);
			if (av[0] == 0)
				continue;
			for (int i = 0; i < 1; i++)
				for (int j = i + 1; j < av[0]; j++) {
					int val = dp[st] + d[get(i) + 1][0]
							+ d[get(j) + 1][0]
							+ d[get(i) + 1][get(j) + 1];
					if (dp[st | (1 << get(i)) | (1 << get(j))] > val) {
						dp[st | (1 << get(i)) | (1 << get(j))] = val;
						dpFrom[st | (1 << get(i)) | (1 << get(j))] = st;
					}
				}
			for (int i = 0; i < 1; i++) {
				int val = dp[st] + d[get(i) + 1][0] * 2;
				if (dp[st | (1 << get(i))] > val) {
					dp[st | (1 << get(i))] = val;
					dpFrom[st | (1 << get(i))] = st;
				}
			}
		}
		out.println(dp[(1 << n) - 1]);
		int nowSt = (1 << n) - 1;
		ArrayList<Integer> ans = new ArrayList<Integer>();
		ans.add(0);
		while (nowSt != 0) {
			int newSt = dpFrom[nowSt];
			for (int i = 0; i < n; i++)
				if (((1 << i) & nowSt) == (1 << i))
					if (((1 << i) & newSt) == 0)
						ans.add(i + 1);
			ans.add(0);
			nowSt = newSt;
		}
		for (int i = ans.size() - 1; i >= 0; i--)
			out.print(ans.get(i) + " ");
	}

	void run() {
		try {
			in = new FastScanner(new File("object.in"));
			out = new PrintWriter(new File("object.out"));

			solve();

			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	void runIO() {

		in = new FastScanner(System.in);
		out = new PrintWriter(System.out);

		solve();

		out.close();
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner(File f) {
			try {
				br = new BufferedReader(new FileReader(f));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}

		public FastScanner(InputStream f) {
			br = new BufferedReader(new InputStreamReader(f));
		}

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

		boolean hasMoreTokens() {
			while (st == null || !st.hasMoreTokens()) {
				String s = null;
				try {
					s = br.readLine();
				} catch (IOException e) {
					e.printStackTrace();
				}
				if (s == null)
					return false;
				st = new StringTokenizer(s);
			}
			return true;
		}

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

		long nextLong() {
			return Long.parseLong(next());
		}
	}

	public static void main(String[] args) {
		new CF8C().runIO();
	}
}


import java.awt.Point;
import java.util.Arrays;
import java.util.Scanner;

public class C {
    static int[] DP;
    static Point[] Next;
    static int[][] pair;
    static int[] single;
    static int n;

    public static int get(int mask) {
        if (mask + 1 == (1 << n))
            return 0;
        if (DP[mask] != -1)
            return DP[mask];
        int x = 0;
        for (;; x++)
            if ((mask & (1 << x)) == 0)
                break;
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            if ((mask & (1 << i)) != 0 || i == x)
                continue;
            int temp = pair[x][i] + get(mask | (1 << i) | (1 << x));
            if (temp < min) {
                min = temp;
                Next[mask] = new Point(x, i);
            }
        }
        int temp = single[x] + get(mask | (1 << x));
        if (temp < min) {
            min = temp;
            Next[mask] = new Point(x, -1);
        }
        return DP[mask] = min;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Point start = new Point(in.nextInt(), in.nextInt());
        n = in.nextInt();
        Point[] A = new Point[n];
        for (int i = 0; i < n; i++)
            A[i] = new Point(in.nextInt(), in.nextInt());
        DP = new int[1 << n];
        Next = new Point[1 << n];
        Arrays.fill(DP, -1);
        pair = new int[n][n];
        single = new int[n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++) {
                int dx1 = A[i].x - start.x;
                int dy1 = A[i].y - start.y;
                int dx2 = A[j].x - A[i].x;
                int dy2 = A[j].y - A[i].y;
                int dx3 = A[j].x - start.x;
                int dy3 = A[j].y - start.y;
                pair[i][j] = dx1 * dx1 + dy1 * dy1 + dx2 * dx2 + dy2 * dy2
                        + dx3 * dx3 + dy3 * dy3;
                single[i] = 2 * (dx1 * dx1 + dy1 * dy1);
            }
        int ans = get(0);
        System.out.println(ans);
        int mask = 0;
        while (mask + 1 != (1 << n)) {
            Point temp = Next[mask];
            if (temp.y == -1)
                System.out.print("0 " + (temp.x + 1) + " ");
            else {
                System.out
                        .print("0 " + (temp.x + 1) + " " + (temp.y + 1) + " ");
                mask |= (1 << temp.y);
            }
            mask |= (1 << temp.x);
        }
        System.out.println("0");
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ProblemC {
	public static void main(String[] args) throws IOException {
		BufferedReader s = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);

		// generateRandom();

		int[] pt = readPoint(s);
		int n = Integer.valueOf(s.readLine());
		int[][] xp = new int[n+1][];
		for (int i = 1 ; i <= n ; i++) {
			xp[i] = readPoint(s);
		}
		xp[0] = pt;

		int[][] dist = new int[n+1][n+1];
		for (int i = 0 ; i <= n ; i++) {
			for (int j = 0 ; j <= n ; j++) {
				int dx = Math.abs(xp[i][0] - xp[j][0]);
				int dy = Math.abs(xp[i][1] - xp[j][1]);
				dist[i][j] = dx*dx + dy*dy;
			}
		}

		int[][] dist2 = new int[n+1][n+1];
		for (int i = 0 ; i <= n ; i++) {
			for (int j = 0 ; j <= n ; j++) {
				dist2[i][j] = dist[0][i] + dist[i][j] + dist[j][0];
			}
		}

		int[] dp = new int[1<<n];
		int[][] dp_prev = new int[2][1<<n];
		Arrays.fill(dp, Integer.MAX_VALUE);
		dp[0] = 0;

		for (int i = 0 ; i < (1<<n) ; i++) {
			if (dp[i] == Integer.MAX_VALUE) {
				continue;
			}
			int base = dp[i];
			// two
			for (int y = 0 ; y < n ; y++) {
				if ((i & (1<<y)) >= 1) {
					break;
				}
				for (int z = y+1 ; z < n ; z++) {
					if ((i & (1<<z)) >= 1) {
						continue;
					}
					int ti = i | (1<<y) | (1<<z);
					int d = dist2[y+1][z+1];
					if (dp[ti] > base + d) {
						dp[ti] = base + d;
						dp_prev[0][ti] = z+1;
						dp_prev[1][ti] = y+1;
					}
				}
			}
		}

		int bestOnes = 0;
		for (int i = 0 ; i < (1<<n) ; i++) {
			if (dp[i] == Integer.MAX_VALUE) {
				continue;
			}
			int sub = (1<<n) - 1 - i;
			int add = 0;
			for (int j = 0 ; j < n ; j++) {
				if ((sub & (1<<j)) >= 1) {
					add += dist[0][j+1] * 2;
				}
			}
			if (dp[i] + add < dp[(1<<n)-1]) {
				dp[(1<<n)-1] = dp[i] + add;
				bestOnes = sub;
			}
		}

		StringBuffer b = new StringBuffer();
		b.append(" 0");
		for (int i = 0 ; i < n ; i++) {
			if ((bestOnes & (1<<i)) >= 1) {
				b.append(" ").append(i+1).append(" ").append(0);
			}
		}

		out.println(dp[(1<<n)-1]);
		int nptn = (1<<n)-1-bestOnes;
		while (nptn >= 1) {
			int i1 = dp_prev[0][nptn];
			int i2 = dp_prev[1][nptn];
			if (i1 >= 1) {
				nptn -= 1<<(i1-1);
				b.append(" ").append(i1);
			}
			if (i2 >= 1) {
				nptn -= 1<<(i2-1);
				b.append(" ").append(i2);
			}
			b.append(" ").append(0);
		}
		out.println(b.substring(1));
		out.flush();
	}

	private static void generateRandom() {
		System.out.println("0 0");
		System.out.println("24");
		for (int i = 0 ; i < 24 ; i++) {
			int a = (int)(Math.random() * 200 - 100);
			int b = (int)(Math.random() * 200 - 100);
			System.out.println(a + " " + b);
		}
	}

	private static int[] readPoint(BufferedReader s) throws IOException {
		int[] ret = new int[2];
		String[] data = s.readLine().split(" ");
		ret[0] = Integer.valueOf(data[0]);
		ret[1] = Integer.valueOf(data[1]);
		return ret;
	}

	public static void debug(Object... os){
		System.err.println(Arrays.deepToString(os));
	}
}


import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

/**
 * @author Egor Kulikov (kulikov@devexperts.com)
 */
public class Order implements Runnable {
	private Scanner in = new Scanner(System.in);
	private PrintWriter out = new PrintWriter(System.out);
	private int xs, ys, n;
	private int[] x, y;

	public static void main(String[] args) {
		new Thread(new Order()).start();
	}

	private void read() {
		xs = in.nextInt();
		ys = in.nextInt();
		n = in.nextInt();
		x = new int[n];
		y = new int[n];
		for (int i = 0; i < n; i++) {
			x[i] = in.nextInt();
			y[i] = in.nextInt();
		}
	}

	private void solve() {
		int[] res = new int[1 << n];
		int[] last = new int[1 << n];
		Arrays.fill(res, Integer.MAX_VALUE);
		int[] ds = new int[n];
		for (int i = 0; i < n; i++) {
			ds[i] = (x[i] - xs) * (x[i] - xs) + (y[i] - ys) * (y[i] - ys);
		}
		int[][] d = new int[n][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++)
				d[i][j] = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);
		}
		res[0] = 0;
		for (int i = 1; i < (1 << n); i++) {
			for (int j = 0; j < n; j++) {
				if (((i >> j) & 1) != 0) {
					if (res[i - (1 << j)] + 2 * ds[j] < res[i]) {
						res[i] = res[i - (1 << j)] + 2 * ds[j];
						last[i] = i - (1 << j);
					}
					for (int k = j + 1; k < n; k++) {
						if (((i >> k) & 1) != 0) {
							if (res[i - (1 << j) - (1 << k)] + ds[j] + ds[k] + d[j][k] < res[i]) {
								res[i] = res[i - (1 << j) - (1 << k)] + ds[j] + ds[k] + d[j][k];
								last[i] = i - (1 << j) - (1 << k);
							}
						}
					}
					break;
				}
			}
		}
		int cur = (1 << n) - 1;
		out.println(res[cur]);
		while (cur != 0) {
			out.print("0 ");
			int dif = cur - last[cur];
			for (int i = 0; i < n && dif != 0; i++) {
				if (((dif >> i) & 1) != 0) {
					out.print((i + 1) + " ");
					dif -= (1 << i);
				}
			}
			cur = last[cur];
		}
		out.println("0");
	}

	private void write() {
	}

	public void run() {
		read();
		solve();
		write();
		out.close();
	}
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

/**
 * 111118315581
 *
 * @author pttrung
 */
public class C {

    static Point hand;
    static int n;
    static Point[] data;
    static int[] next;
    static int[] dp;
    static int[][] pre;

    public static void main(String[] args) {
        Scanner in = new Scanner();
        PrintWriter out = new PrintWriter(System.out);
        // System.out.println(1 << 24);
        hand = new Point(in.nextInt(), in.nextInt());
        n = in.nextInt();
        data = new Point[n];
        for (int i = 0; i < n; i++) {
            data[i] = new Point(in.nextInt(), in.nextInt());
        }
        pre = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                pre[i][j] = distance(data[i], data[j]);
            }
        }

        next = new int[1 << n];
        dp = new int[1 << n];
        Arrays.fill(dp, -1);

        out.println(cal(0));

        int start = 0;

        do {
            int m = next[start];
            int val = m - start;
            out.print(0 + " ");
            for (int i = 0; i < n; i++) {
                if (((1 << i) & val) != 0) {
                    out.print((i + 1) + " ");
                }
            }
            // out.print(0 + " ")  ;
            start = m;
        } while (start != (1 << n) - 1);
        out.println(0);
        out.close();
    }

    public static int cal(int mask) {
        if ((1 << n) - 1 == mask) {
            //  System.out.println(mask);
            return 0;
        }
        if (dp[mask] != -1) {
            return dp[mask];
        }
        int result = Integer.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            if (((1 << i) & mask) == 0) {
                int dist = distance(hand, data[i]);

                for (int j = i + 1; j < n; j++) {
                    if (((1 << j) & mask) == 0) {
                        //System.out.println(i + " " + j);
                        int temp = dist + distance(hand, data[j]) + pre[i][j] + cal(mask | (1 << i) | (1 << j));
                        //System.out.println(temp);
                        if (temp < result) {
                            result = temp;
                            next[mask] = (mask | (1 << i) | (1 << j));
                        }

                    }
                }

                    int temp = 2 * dist + cal(mask | (1 << i));
                    if (temp < result) {
                        result = temp;
                        next[mask] = (mask | (1 << i));
                    }

                break;
            }

        }
        dp[mask] = result;
        return result;
    }

    static int distance(Point a, Point b) {
        int total = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
        return total;
    }

    static class Point {

        int x, y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;

        }
    }

    static class Scanner {

        BufferedReader br;
        StringTokenizer st;

        public Scanner() {
            // System.setOut(new PrintStream(new BufferedOutputStream(System.out), true));
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public String next() {

            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    throw new RuntimeException();
                }
            }
            return st.nextToken();
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

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

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public String nextLine() {
            st = null;
            try {
                return br.readLine();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }

        public boolean endLine() {
            try {
                String next = br.readLine();
                while (next != null && next.trim().isEmpty()) {
                    next = br.readLine();
                }
                if (next == null) {
                    return true;
                }
                st = new StringTokenizer(next);
                return st.hasMoreTokens();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;

import static java.lang.Integer.MAX_VALUE;
import static java.lang.Integer.parseInt;

/**
 * 8C
 *
 * @author artyom
 */
public class LookingForOrder {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String[] parsedString = parsedString = in.readLine().split(" ");
        int xStart = parseInt(parsedString[0]);
        int yStart = parseInt(parsedString[1]);
        int objectNum = parseInt(in.readLine());

        int[] xLocs = new int[objectNum + 1];
        int[] yLocs = new int[objectNum + 1];
        int[] bitMasks = new int[1 << objectNum];
        Arrays.fill(bitMasks, MAX_VALUE);
        int[] previous = new int[1 << objectNum];

        xLocs[objectNum] = xStart;
        yLocs[objectNum] = yStart;
        for (int i = 0; i < objectNum; i++) {
            parsedString = in.readLine().split(" ");
            xLocs[i] = parseInt(parsedString[0]);
            yLocs[i] = parseInt(parsedString[1]);
        }

        //go through all pairs and find time requirement for each pair of objects
        //the entry at point [i][j] is equal to the time it takes to get from point i to point j
        int[][] times = new int[objectNum + 1][objectNum + 1];
        for (int i = 0; i <= objectNum; i++) {
            for (int j = 0; j <= objectNum; j++) {
                times[i][j] = times[j][i] = (xLocs[i] - xLocs[j]) * (xLocs[i] - xLocs[j]) + (yLocs[i] - yLocs[j]) * (yLocs[i] - yLocs[j]);
            }
        }

        //each value in bitmasks represents the minimum time necessary to get
        //the unmasked bits
        //so bitmasks[5] (5=101) is the fastest time in which you can get
        //items 1 and 3
        bitMasks[0] = 0; //collecting zero objects takes 0 time
        for (int i = 0; i < (1 << objectNum); i++) {
            if (bitMasks[i] != MAX_VALUE) {
                for (int j = 0; j < objectNum; j++) {
                    if (((1 << j) & i) == 0) { //if our current j object hasn't been picked up yet
                        int curState = (1 << j) | i; //ith state after picking up j object
                        int curTime = bitMasks[i] + 2 * times[objectNum][j]; //time required to get object j from bag at state i

                        if (curTime < bitMasks[curState]) {
                            bitMasks[curState] = curTime; //put fastest time in for gettingto our current state
                            previous[curState] = i;
                        }

                        //find another thing while you're out
                        for (int k = 0; k < objectNum; k++) {
                            if (((1 << k) & curState) == 0) { //if the kth position in our current state hasn't been picked up
                                int kState = ((1 << k) | curState); //curstate after picking up the kth object
                                //kTime is time it takes to go from bag, to j, to k and back
                                int kTime = bitMasks[i] + times[objectNum][j] + times[j][k] + times[k][objectNum];

                                if (kTime < bitMasks[kState]) {
                                    bitMasks[kState] = kTime;  //put shortest time for getting to kState in
                                    previous[kState] = i;
                                }
                            }
                        }
                        break;
                    }
                }
            }
        }

        int finalState = (1 << objectNum) - 1;

        StringBuilder sb = new StringBuilder();
        sb.append(bitMasks[finalState]).append('\n');

        Deque<Integer> outputQ = new ArrayDeque<>();
        outputQ.add(0);
        int curState = finalState;
        while (curState > 0) {
            //difference is the objects picked up in this state but not in previous state
            int difference = curState ^ previous[curState];
            int firstItem = -1;
            int secondItem = -1;

            for (int i = 0; i < objectNum; i++) {
                if (((1 << i) & difference) > 0) { //if the ith object was picked up in this state
                    secondItem = firstItem; //keep track of how many items are picked up
                    firstItem = i;
                }
            }

            if (secondItem != -1) {
                //put in two items followed by a return to 0
                outputQ.add(firstItem + 1);
                outputQ.add(secondItem + 1);
                outputQ.add(0);
            } else {
                outputQ.add(firstItem + 1);
                outputQ.add(0);
            }

            curState = previous[curState];
        }

        sb.append(outputQ.removeLast());
        while (!outputQ.isEmpty()) {
            sb.append(' ').append(outputQ.removeLast());
        }
        System.out.print(sb);
    }
}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class LookingForOrder {
	static final int INF = (int)1e9;
	static Point a[];
	static Point o;
	static int n;
	static int dp[];
	static PrintWriter out;

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);

		o = new Point(sc.nextInt(), sc.nextInt());
		n = sc.nextInt();
		a = new Point[n];
		for (int i = 0; i < n; i++)
			a[i] = new Point(sc.nextInt(), sc.nextInt());

		dp = new int[(1 << n) + 5];
		Arrays.fill(dp, -1);
		out.println(rec(0));
		out.print(0 + " ");
		path(0);
		out.println();

		out.flush();
		out.close();
	}

	static void path(int msk) {
		if (msk == (1 << n) - 1) return;

		int optimal = rec(msk);
		for (int i = 0; i < n; i++) {
			if ((msk & (1 << i)) == 0) {
				if (rec(msk | (1 << i)) + 2 * o.dist(a[i]) == optimal) {
					out.print((i + 1) + " " + 0 + " ");
					path(msk | (1 << i));
					return;
				}

				for (int j = 0; j < n; j++)
					if (rec(msk | (1 << i) | (1 << j)) + o.dist(a[i]) + a[i].dist(a[j]) + a[j].dist(o) == optimal) {
						out.print((i + 1) + " " + (j + 1) + " " + 0 + " ");
						path(msk | (1 << i) | (1 << j));
						return;
					}
				break;
			}
		}
	}

	static int rec(int msk) {
		if (msk == (1 << n) - 1) return 0;
		if (dp[msk] != -1) return dp[msk];

		int ans = INF;
		for (int i = 0; i < n; i++) {
			if ((msk & (1 << i)) == 0) {
				ans = Math.min(ans, rec(msk | (1 << i)) + 2 * o.dist(a[i]));
				for (int j = 0; j < n; j++) {
					if (i == j) continue;
					if ((msk & (1 << j)) == 0)
						ans = Math.min(ans, rec(msk | (1 << i) | (1 << j)) + o.dist(a[i]) + a[i].dist(a[j]) + a[j].dist(o));
				}
				break;
			}
		}

		return dp[msk] = ans;
	}

	static class Point {
		int x, y;

		public Point(int x, int y) {
			this.x = x;
			this.y = y;
		}

		public int dist(Point p) {
			return (x - p.x) * (x - p.x) + (y - p.y) * (y - p.y);
		}
	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		public Scanner(FileReader f) {
			br = new BufferedReader(f);
		}

		public Scanner(InputStream in) {
			br = new BufferedReader(new InputStreamReader(in));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

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

		public long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public boolean Ready() throws IOException {
			return br.ready();
		}

		public void waitForInput(long time) {
			long ct = System.currentTimeMillis();
			while(System.currentTimeMillis() - ct < time) {};
		}

	}

}


import java.io.*;
import java.util.*;

public class Main {

    BufferedReader in = null;
    PrintWriter out = null;

    int dist(int x1, int y1, int x2, int y2) {
        int dx = Math.abs(x1 - x2);
        int dy = Math.abs(y1 - y2);
        return dx * dx + dy * dy;
    }

    boolean testBit(int use, int p) {
        return ((use >> p) & 1) == 1;
    }

    int rec(int use, int a[][], int dp[], int next[]) {
        if (dp[use] != -1) {
            return dp[use];
        }
        if (use == 0) {
            return dp[use] = 0;
        }
        int n = a.length;
        int ix = -1;

        for (int i = 0; i < n; ++i) {
            if (testBit(use, i)) {
                if (ix == -1) {
                    ix = i;
                    break;
                }

                /*
                int t = rec(use ^ (1 << i), a, dp);
                t += a[i][i];
                r = Math.min(r, t);*/
            }
        }

        int r = rec(use ^ (1 << ix), a, dp, next) + a[ix][ix];
        next[use] = use ^ (1 << ix);

        for (int i = ix + 1; i < n; ++i) {
            if (!testBit(use, i)) {
                continue;
            }
            int t = rec(use ^ (1 << ix) ^ (1 << i), a, dp, next);
            t += a[ix][i];
            if (t < r) {
                r = t;
                next[use] = use ^ (1 << ix) ^ (1 << i);
            }
        }

        return dp[use] = r;
    }

    void print(int use1, int use2, int n) {
        for (int i = 0; i < n; ++i) {
            if (testBit(use1, i) ^ testBit(use2, i)) {
                int x = i + 1;
                out.print(x + " ");
            }
        }
    }

    void solve() throws IOException {
        in = new BufferedReader(new InputStreamReader(System.in));
        //in = new BufferedReader(new FileReader("input.txt"));
        out = new PrintWriter(System.out);

        StringTokenizer st;
        st = new StringTokenizer(in.readLine());
        int sx = Integer.valueOf(st.nextToken());
        int sy = Integer.valueOf(st.nextToken());
        st = new StringTokenizer(in.readLine());
        int n = Integer.valueOf(st.nextToken());
        int x[] = new int[n];
        int y[] = new int[n];
        for (int i = 0; i < n; ++i) {
            st = new StringTokenizer(in.readLine());
            x[i] = Integer.valueOf(st.nextToken());
            y[i] = Integer.valueOf(st.nextToken());
        }
        int a[][] = new int[n][n];
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                a[i][j] = dist(x[i], y[i], sx, sy) + dist(x[j], y[j], sx, sy) + dist(x[i], y[i], x[j], y[j]);
            }
        }

        int dp[] = new int[1 << n];
        Arrays.fill(dp, -1);
        int next[] = new int[1 << n];
        int ans = rec((1 << n) - 1, a, dp, next);

        out.println(ans);

        int use = (1 << n) - 1;
        while (true) {
            int nuse = next[use];
            out.print("0 ");
            print(use, nuse, n);
            if (nuse == 0) break;
            use = nuse;
        }
        out.println("0");

        in.close();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new Main().solve();
    }

}


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

public class C {
    static int[] dp;
    static int[] f;
    static void solve(){
        dp = new int[1<<n];
        f  = new int[1<<n];
        Arrays.fill(dp, 1<<29);
        dp[0] = 0;
        for(int i=0;i<(1<<n);i++){
//            out.println("i="+i);
            for(int j=0;j<n;j++){
                int ni = i | (1<<j);
                if( i != ni ){
//                    out.println("i="+i+",j="+j);
                    int v = d[j]*2 + dp[i];
                    if(v < dp[ni]){
//                        out.println("up:"+ni+" to "+v + " fw="+i);
                        dp[ni] = v;
                        f[ni] = i;
                    }

                    for(int k=j+1;k<n;k++){
                        int nni = ni | (1<<k);
                        if( ni != nni){
                            int vv = d[j] + t[j][k] + d[k] + dp[i];
                            if(vv < dp[nni]){
//                                out.println("up:"+nni+" to "+vv + " fw="+i);
                                dp[nni] = vv;
                                f[nni] = i;
                            }
                        }
                    }
                    break;
                }
            }
        }
        out.println(dp[dp.length-1]);
//        out.println("dp="+Arrays.toString(dp));
//        out.println("f="+Arrays.toString(f));

        int idx = dp.length - 1;
        out.print("0 ");
        while(idx != 0){
            int road = idx ^ f[idx];
//            out.println("idx = "+idx + " f[idx] = "+f[idx]);
            for(int i=0;i<n;i++) if( ((road>>i) & 1) == 1) out.print((i+1)+" ");
            idx = f[idx];
            out.print("0 ");
        }
        out.println();
    }
    static int[] d;
    static int[][] t;
    static int n;
    public static void main(String[] args) {
        Scanner sc = new Scanner(in);

        int x = sc.nextInt();
        int y = sc.nextInt();

        n = sc.nextInt();
        int[] dx = new int[n];
        int[] dy = new int[n];

        for(int i=0;i<n;i++){
            dx[i] = sc.nextInt();
            dy[i] = sc.nextInt();
        }

        d = new int[n];
        for(int i=0;i<n;i++){
            d[i] = (x-dx[i])*(x-dx[i]) + (y-dy[i])*(y-dy[i]);
        }

        t = new int[n][n];
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                t[i][j] = (dx[i]-dx[j])*(dx[i]-dx[j]) + (dy[i]-dy[j])*(dy[i]-dy[j]);
            }
        }
//        out.println(Arrays.toString(d));
//        out.println(Arrays.deepToString(t));

        solve();
    }
}