Problem:
Score : 300 points

Problem Statement

You are given an undirected unweighted graph with N vertices and M edges that contains neither self-loops nor double edges.

Here, a self-loop is an edge where a_i = b_i (1≤i≤M), and double edges are two edges where (a_i,b_i)=(a_j,b_j) or (a_i,b_i)=(b_j,a_j) (1≤i<j≤M).

How many different paths start from vertex 1 and visit all the vertices exactly once?

Here, the endpoints of a path are considered visited.

For example, let us assume that the following undirected graph shown in Figure 1 is given.

Figure 1: an example of an undirected graph

The following path shown in Figure 2 satisfies the condition.

Figure 2: an example of a path that satisfies the condition

However, the following path shown in Figure 3 does not satisfy the condition, because it does not visit all the vertices.

Figure 3: an example of a path that does not satisfy the condition

Neither the following path shown in Figure 4, because it does not start from vertex 1.

Figure 4: another example of a path that does not satisfy the condition

Constraints

2≦N≦8

0≦M≦N(N-1)/2

1≦a_i<b_i≦N

The given graph contains neither self-loops nor double edges.

Input

The input is given from Standard Input in the following format:

N M
a_1 b_1
a_2 b_2
:
a_M b_M

Output

Print the number of the different paths that start from vertex 1 and visit all the vertices exactly once.

Sample Input 1

3 3
1 2
1 3
2 3

Sample Output 1

2

The given graph is shown in the following figure:

The following two paths satisfy the condition:

Sample Input 2

7 7
1 3
2 7
3 4
4 5
4 6
5 6
6 7

Sample Output 2

1

This test case is the same as the one described in the problem statement.

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
 
#ifndef LOCAL_
#define fprintf if( false ) fprintf
#endif // LOCAL_
#define dumpl(x1) fprintf(stderr, "#%s.%d (%s) = (%ld)\n", __func__, __LINE__, #x1, x1);
#define dumpll(x1, x2) fprintf(stderr, "#%s.%d (%s, %s) = (%ld, %ld)\n", __func__, __LINE__, #x1, #x2, x1, x2);
#define dumpd(x1) fprintf(stderr, "#%s.%d (%s) = (%lf)\n", __func__, __LINE__, #x1, x1);
#define dumpdd(x1, x2) fprintf(stderr, "#%s.%d (%s, %s) = (%lf, %lf)\n", __func__, __LINE__, #x1, #x2, x1, x2);
#define loop for(;;)
 
struct S002 {
  int n;
  S002& operator > (long& x) {
    n = x;
    return *this;
  }
  S002& operator > (long&& x) {
    n = x;
    return *this;
  }
  S002& operator >= (long& x) {
    if( scanf("%ld", &x) <= 0 ) exit(0);
    return *this;
  }
  S002& operator >= (double& x) {
    if( scanf("%lf", &x) <= 0 ) exit(0);
    return *this;
  }
  S002& operator >= (std::string& s) {
    if( not (std::cin >> s) ) exit(0);
    return *this;
  }
  template<typename a>
  S002& operator >= (std::vector<a>& v) {
    v.resize(n);
    for(long i = 0; i < n; ++i) {
      *this >= v[i];
    }
    return *this;
  }
  template<typename a, std::size_t s>
  S002& operator >= (std::array<a, s>& x) {
    for(long i = 0; i < (long)s; ++i) {
      *this >= x[i];
    }
    return *this;
  }
};

struct S004 {
  S004() : s(-1), d(-1) {}             
  S004(int s_, int d_) : s(s_), d(d_) {}
  long s, d;
};

template<typename a>
struct S005 {
  typedef a e;
  std::vector<std::vector<a>> xs;
  const std::vector<a>& ys;
  long n;
  S005(const std::vector<a>& ys_, long n_) : ys(ys_), n(n_) {
    xs.resize(n);
    for(a x : ys) {
      a y = x;
      xs[x.s].push_back(y);
    }
  }
  const std::vector<a>& operator [] (long i) const {
    return xs[i];
  }
  long v() const {
    return n;
  }
  const std::vector<a>& es() const {
    return ys;
  }
};

template<typename a>
struct S026 {
  std::vector<std::vector<long>> xs;
  long n;
  S026(const a& graph, long src) : n(graph.v()) {
    std::vector<bool> visited(n, false);
    std::vector<long> path;
    dfs(graph, src, visited, 0, path);
  }
  void dfs(const a& graph, long i, std::vector<bool>& visited, long d, std::vector<long>& path) {
    if( d == n - 1 ) {
      xs.push_back(path);
      return;
    }
    visited[i] = true;
    path.push_back(i);
    for(typename a::e edge : graph[i]) {
      if( visited[edge.d] ) continue;
      dfs(graph, edge.d, visited, d + 1, path);
    }
    path.pop_back();
    visited[i] = false;
  }
  typename std::vector<std::vector<long>>::iterator begin() { return xs.begin(); }
  typename std::vector<std::vector<long>>::iterator end() { return xs.end(); }
  long size() const {
    return xs.size();
  }
};

struct Solver {
  long n, m;
  std::vector<std::array<long, 2>> xs;
  Solver() {
    S002 reader;
    reader >= n >= m >m>= xs;
  }
  void solve() {
    std::vector<S004> edges;
    for(std::array<long, 2> e : xs) {
      e[0] -= 1, e[1] -= 1;
      edges.push_back(S004(e[0], e[1]));
      edges.push_back(S004(e[1], e[0]));
    }
    S005<S004> graph(edges, n);
    S026<S005<S004>> ham(graph, 0);
    long res = ham.size();
    printf("%ld\n", res);
  }
  // long dfs(const S005<S004>& graph, long i, std::vector<bool>& visited, long d) {
  //   if( d == n - 1 ) return 1;
  //   long res = 0;
  //   visited[i] = true;
  //   for(S004 edge : graph[i]) {
  //     if( visited[edge.d] ) continue;
  //     res += dfs(graph, edge.d, visited, d + 1);
  //   }
  //   visited[i] = false;
  //   return res;
  // }
};
 
int main() {
  loop std::unique_ptr<Solver>(new Solver())->solve();
  return 0;
}