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.Collections.Generic;
using System.Linq;

namespace AtConderBeginnerContest054
{
    class ProgramC
    {
        static void Main(string[] args)
        {
            string szTotal = Console.ReadLine();
            string[] szArr = szTotal.Split(' ');
            int n = int.Parse(szArr[0]);
            int m = int.Parse(szArr[1]);

            int[] a = new int[m];
            int[] b = new int[m];
            for (int i = 0; i < a.Length; ++i)
            {
                string szLine = Console.ReadLine();
                szArr = szLine.Split(' ');
                a[i] = int.Parse(szArr[0]);
                b[i] = int.Parse(szArr[1]);
            }

            int result = Solve(a, b, n);
            Console.WriteLine(result);
        }
        private static int Solve(int[] a, int[] b, int n)
        {
            // 木構造で作成
            Node root = new Node(1, 1, n, null);
            CreateLeaf(root, a, b, n);

            // depthが最大までいったのをカウント
            int total = 0;
            CountTree(root, ref total, n);

            return total;
        }

        private static void CreateLeaf(Node node, int[] a, int[] b, int n)
        {
            int id = node._id;
            for (int i = 0; i < a.Length; ++i)
            {
                if (a[i] != id && b[i] != id) { continue; }

                int nextid = 0;
                if (a[i] == id) { nextid = b[i]; }
                else { nextid = a[i]; }

                // これは使用済みの辺かもしれない
                if(node.IsExists(nextid)) { continue; }

                Node leaf = new Node(nextid, node._depth + 1, n, node);
                node._leaf[nextid - 1] = leaf;
                CreateLeaf(leaf, a, b, n);
            }
        }

        private class Node
        {
            public int _id = 1;
            public int _depth = 1;
            public Node _parent = null;
            public Node[] _leaf = null;
            /// <summary>
            /// 
            /// </summary>
            /// <param name="id"></param>
            /// <param name="depth">1 以上</param>
            /// <param name="n"></param>
            public Node(int id, int depth, int n, Node parent)
            {
                _id = id;
                _depth = depth;
                _parent = parent;
                _leaf = new Node[n];
            }

            /// <summary>
            /// 親も含め存在しているか？
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public bool IsExists(int id)
            {
                if (_id == id) { return true; }

                if (_parent == null) { return false; }

                return _parent.IsExists(id);
            }
        }

        private static void CountTree(Node node, ref int total, int maxdepth)
        {
            if( node._depth == maxdepth)
            {
                ++total;
            }
            foreach(Node leaf in node._leaf)
            {
                if( leaf == null) { continue; }

                CountTree(leaf ,ref total, maxdepth);

            }
        }
    }


}