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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text;


class Program
{
    static bool[] visited;
    static bool[,] connect;
    static int N;
    static int M;
    static List<string> list;
    static void Main(string[] args)
    {
        int[] input = Console.ReadLine().Split().Select(int.Parse).ToArray();
        N = input[0];
        M = input[1];

        //無向グラフ
        connect = new bool[N, N];
        visited = new bool[N];

        int[] a = new int[M];
        int[] b = new int[M];
        for (int i = 0; i < M; i++)
        {
            input = Console.ReadLine().Split().Select(int.Parse).ToArray();
            a[i] = input[0] - 1;
            b[i] = input[1] - 1;
            connect[a[i], b[i]] = true;
            connect[b[i], a[i]] = true;
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < N; i++)
        {
            sb.Append(i.ToString());
        }
        var tmp = sb.ToString();

        list = new List<string>();
        int res = 0;

        for (int j = 0; j < N; j++) visited[j] = false;

        dfs("0", N, 1);

        foreach (var item in list)
        {
            var c = item.ToCharArray();
            Array.Sort(c);
            var s = new string(c);
            if (s == tmp) res++;
        }

        Console.WriteLine(res);

    }
    static void dfs(string text, int n, int depth)
    {
        if (depth == n)
        {
            list.Add(text);
        }
        else
        {
            ++depth;

            if (text.Length < N && text[text.Length - 1] == '0')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[0, i]) dfs(text + i.ToString(), n, depth);
                }
            }
            if (text.Length < N && text[text.Length - 1] == '1')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[1, i]) dfs(text + i.ToString(), n, depth);
                }
            }
            if (text.Length < N && text[text.Length - 1] == '2')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[2, i]) dfs(text + i.ToString(), n, depth);
                }
            }
            if (text.Length < N && text[text.Length - 1] == '3')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[3, i]) dfs(text + i.ToString(), n, depth);
                }
            }
            if (text.Length < N && text[text.Length - 1] == '4')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[4, i]) dfs(text + i.ToString(), n, depth);
                }
            }
            if (text.Length < N && text[text.Length - 1] == '5')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[5, i]) dfs(text + i.ToString(), n, depth);
                }
            }
            if (text.Length < N && text[text.Length - 1] == '6')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[6, i]) dfs(text + i.ToString(), n, depth);
                }
            }
            if (text.Length < N && text[text.Length - 1] == '7')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[7, i]) dfs(text + i.ToString(), n, depth);
                }
            }
            if (text.Length < N && text[text.Length - 1] == '8')
            {
                for (int i = 0; i < N; i++)
                {
                    if (connect[8, i]) dfs(text + i.ToString(), n, depth);
                }
            }
        }
    }
}