#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

typedef struct int_list_elem_t {
  int data;
  struct int_list_elem_t* prev;
  struct int_list_elem_t* next;
} int_list_elem;

typedef struct int_list_t {
  int_list_elem* head;
  int_list_elem* tail;
  unsigned long length;
} int_list;

int_list* int_list_init() {
  int_list* lst = (int_list*)calloc(1, sizeof(int_list));
  return lst;
}

unsigned long int_list_length(const int_list* lst) {
  return lst->length;
}
  
int int_list_get(const int_list* lst, unsigned long index) {
  if (lst->length <= index || index < 0) {
    printf("index out of range exception\n");
    exit(EXIT_FAILURE);
  }
  unsigned long i;
  int_list_elem* obtained_elem;
  if (index <= lst->length / 2) {
    obtained_elem = lst->head;
    for (i = 0; i < index; i++) {
      obtained_elem = obtained_elem->next;
    }
  } else {
    obtained_elem = lst->tail;
    for (i = lst->length - 1; i > index; i--) {
      obtained_elem = obtained_elem->prev;
    }
  }
  return obtained_elem->data;
}

void int_list_add(int_list* lst, unsigned long index, int data) {
  if (lst->length < index || index < 0) {
    printf("index out of range exception\n");
    exit(EXIT_FAILURE);
  }
  if (lst->length >= ULONG_MAX) {
    printf("list overflow\n");
    exit(EXIT_FAILURE);
  }

  int_list_elem* added_elem = (int_list_elem*)malloc(sizeof(int_list_elem));
  int_list_elem* elem;
  unsigned long i;
  added_elem->data = data;
  if (index == 0) {
    added_elem->prev = NULL;
    added_elem->next = lst->head;
    lst->head     = added_elem;
    if (added_elem->next == NULL) // if list length = 0
      lst->tail = added_elem;
    else
      added_elem->next->prev = added_elem;
  } else if (index == lst->length) {
    added_elem->next = NULL;
    added_elem->prev = lst->tail;
    lst->tail     = added_elem;
    // added_elem->prev != NULL because length != 0
    added_elem->prev->next = added_elem;
  } else {
    if (index <= lst->length / 2) {
      elem = lst->head;
      for (i = 0; i < index; i++) {
        elem = elem->next;
      }
    } else {
      elem = lst->tail;
      for (i = lst->length - 1; i > index; i--) {
        elem = elem->prev;
      }
    }
    elem->prev->next = added_elem;
    added_elem->prev = elem->prev;
    elem->prev       = added_elem;
    added_elem->next = elem;
  }
  lst->length++;
}

void int_list_remove(int_list* lst, unsigned long index) {
  if (lst->length <= index || index < 0) {
    printf("index out of range exception\n");
    exit(EXIT_FAILURE);
  }
  unsigned long i;
  int_list_elem* obtained_elem;
  if (index == 0) {
    obtained_elem = lst->head;
    lst->head = lst->head->next;
    if (lst->head == NULL)
      lst->tail = NULL;
    else
      lst->head->prev = NULL;
  } else if (index == lst->length - 1) {
    obtained_elem = lst->tail;
    lst->tail = lst->tail->prev;
    lst->tail->next = NULL;
  } else {
    if (index <= lst->length / 2) {
      obtained_elem = lst->head;
      for (i = 0; i < index; i++) {
        obtained_elem = obtained_elem->next;
      }
    } else {
      obtained_elem = lst->tail;
      for (i = lst->length - 1; i > index; i--) {
        obtained_elem = obtained_elem->prev;
      }
    }
    obtained_elem->prev->next = obtained_elem->next;
    obtained_elem->next->prev = obtained_elem->prev;
  }
  free(obtained_elem);
  lst->length--;
}

void int_list_delete(int_list* lst) {
  while (lst->length) {
    int_list_remove(lst, 0);
  }
  free(lst);
}

long count_one_stroke_path(int N, const int* pass, int_list** edge_list, int now) {
  long count = 0;
  int i, j;
  int next;
  int* next_pass;
  int goal = 1;
  int failure = 1;
  for (i = 0; i < N; i++) {
    if (pass[i] != 1) {
      goal = 0;
      break;
    }
  }
  if (goal) return 1;
  for (i = 0; i < edge_list[now]->length; i++) {
    next = int_list_get(edge_list[now], i);
    if (pass[next] == 0) {
      next_pass = (int*)malloc(sizeof(int) * N);
      for (j = 0; j < N; j++)
        next_pass[j] = pass[j];
      next_pass[next] = 1;
      count += count_one_stroke_path(N, next_pass, edge_list, next);
      failure = 0;
      free(next_pass);
    }
  }
  if (failure) return 0;
  return count;
}

int main() {
  int N, M;
  scanf("%d %d%*c", &N, &M);
  int* a, *b;
  a = (int*)malloc(sizeof(int) * M);
  b = (int*)malloc(sizeof(int) * M);
  int i, j;
  for (i = 0; i < M; i++) {
    scanf("%d %d%*c", &(a[i]), &(b[i]));
    a[i] -= 1;
    b[i] -= 1;
  }
  int_list** edge_list = (int_list**)malloc(sizeof(int_list*) * N);
  for (j = 0; j < N; j++) {
    edge_list[j] = int_list_init();
  }
  for (i = 0; i < M; i++) {
    for (j = 0; j < N; j++) {
      if (a[i] == j)
        int_list_add(edge_list[j], 0, b[i]);
      if (b[i] == j)
        int_list_add(edge_list[j], 0, a[i]);
    }
  }
  
  int* pass = (int*)calloc(N, sizeof(int));
  pass[0] = 1;
  printf("%ld\n", count_one_stroke_path(N, pass, edge_list, 0));
  
  
  free(a);
  free(b);
  for (j = 0; j < N; j++)
    int_list_delete(edge_list[j]);
  free(edge_list);
  free(pass);
  return 0;
}


Measured memory_bytes: 128