// 状压表示点的集合
// 每次尝试加入一个点，看能不能构成一个完全图
// 若能，则这个点集的完全图数为1
// 否则采用环形DP的方法求最小完全图数
// 太菜了，写不出来QAQ

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define INF 0x3f3f3f3f

using namespace std;

const int maxn = 18;

int n, m;
int grap[maxn + 1][maxn + 1];
int f[1 << maxn], good[1 << maxn];

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++) {
        int a, b;
        scanf("%d%d", &a, &b);
        grap[a][b] = 1;
        grap[b][a] = 1;
    }

    for (int i = 1; i < (1 << n); i++) {
        vector<int> u;
        for (int j = 1; j <= n; j++) {
            if (i & (1 << (j - 1))) u.push_back(j);
        }
        good[i] = true;
        for (int j = 0; j < u.size(); j++) {
            for (int k = j + 1; k < u.size(); k++) {
                if (!grap[u[j]][u[k]]) good[i] = false;
            }
        }
    }

    for (int i = 1; i < (1 << n); i++)
        f[i] = INF;

    for (int i = 1; i < (1 << n); i++) {
        if (good[i]) {
            f[i] = 1;
            continue;
        }
        for (int j = i; j; j = (j - 1) & i) {
            f[i] = min(f[i], f[j] + f[i ^ j]);
        }
    }

    printf("%d\n", f[(1 << n) - 1]);
    return 0;
}
#include<bits/stdc++.h>
using ll = int_fast64_t;
using P = std::pair<ll,ll>;
using PP = std::pair<ll,P>;

#define REP(i,b,e) for(int i=b; i<e; i++)
#define PRINT(vec) {printf("[ ");for(auto &i:vec)printf("%ld ",i);puts("]");}
#define fi first
#define se second

const int MOD = 1e9+7;
int dx[] = {0, 1, 0, -1, 1, 1, -1, -1}, dy[] = {1, 0, -1, 0, 1, -1, -1, 1};

int main(){
    ll n, k;
    scanf("%ld %ld", &n, &k);
    ll dist[n][n];
    REP(i, 0, n) REP(j, 0, n) scanf("%ld", &dist[i][j]);

    ll ans = 0;
    ll a[n-1];
    REP(i, 0, n-1) a[i] = i+1;
    do{
        ll tmp = dist[0][a[0]];
        REP(i, 1, n-1){
            tmp += dist[a[i-1]][a[i]];
        }
        tmp += dist[a[n-2]][0];
        if(tmp==k) ans++;
    }while(std::next_permutation(a, a+n-1));

    printf("%ld\n", ans);
    return 0;
}