#include <bits/stdc++.h>
const long long INF32 = 1e9;
const long long INF64 = 1e17;
const int RANGE = 1e6 + 5;
using namespace std;
template <class T>
void read(T &Val) {
  T tmp = 0;
  char ch = getchar();
  int flag = 1;
  while (!(ch >= '0' && ch <= '9')) {
    if (ch == '-') flag = -1;
    ch = getchar();
  }
  while ((ch >= '0' && ch <= '9')) {
    tmp = tmp * 10 + ch - '0';
    ch = getchar();
  }
  Val = flag * tmp;
}
int edge[30][30];
long long dp[1 << 20][20];
int graph[RANGE];
int bits[RANGE];
int vertice[30];
bool cmp(int &a, int &b) { return bits[b] > bits[a]; }
int lowbit(int a) {
  if (a == 0) return 0;
  int now = 1;
  while ((a & 1) == 0) a = a >> 1, now++;
  return now - 1;
}
int main() {
  int n, m;
  read(n), read(m);
  for (int i = 0; i < m; i++) {
    int a, b;
    read(a), read(b);
    a--, b--;
    edge[a][b]++;
    edge[b][a]++;
  }
  for (int i = 0; i <= (1 << n); i++) {
    graph[i] = i;
    bits[i] = __builtin_popcount(i);
  }
  sort(graph, graph + (1 << n), cmp);
  for (int mask = 0; mask < (1 << n); mask++) {
    if (__builtin_popcount(graph[mask]) == 1) {
      dp[graph[mask]][lowbit(graph[mask])] = 1;
      continue;
    }
    for (int i = 0; i < n; i++) {
      if (lowbit(graph[mask]) == i) continue;
      for (int j = 0; j < n; j++) {
        if (edge[i][j]) {
          dp[graph[mask]][i] += dp[graph[mask] ^ (1 << i)][j];
        }
      }
    }
  }
  long long ans = 0;
  for (int mask = 0; mask < (1 << n); mask++) {
    if (__builtin_popcount(graph[mask]) < 3) continue;
    for (int i = 0; i < n; i++) {
      if (edge[lowbit(graph[mask])][i]) ans += dp[graph[mask]][i];
    }
  }
  cout << ans / 2 << endl;
  return 0;
}
