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)

#region using
using System;
using System.Collections.Generic;
using System.Linq;
using IEnumerable = System.Collections.IEnumerable;
using IEnumerator = System.Collections.IEnumerator;
using BitArray = System.Collections.BitArray;
using BigInteger = System.Numerics.BigInteger;
using TextReader = System.IO.TextReader;
using System.Text;
#endregion

namespace AtCoderProject
{
    public class Program
    {
        public object Calc()
        {
            var N = consoleReader.Int;
            var M = consoleReader.Int;
            var gb = new GraphBuilder(N);
            foreach (var cr in consoleReader.Repeat(M))
                gb.Add(cr.Int - 1, cr.Int - 1);
            graph = gb.ToArray();

            return ZeroEnumerate(Enumerable.Range(1, N - 1).ToArray()).Count(IsValid);
        }

        bool IsValid(int[] pr)
        {
            for (int i = 0; i < pr.Length - 1; i++)
                if (Array.IndexOf(graph[pr[i]], pr[i + 1]) < 0) return false;
            return true;
        }

        int[][] graph;
        static IEnumerable<int[]> ZeroEnumerate(IReadOnlyCollection<int> items)
        {
            foreach (var p in Enumerate(items))
            {
                var pr = new int[items.Count + 1];
                p.CopyTo(pr, 1);
                yield return pr;
            }
        }


        class GraphBuilder
        {
            public List<int>[] lists;
            public GraphBuilder(int count)
            {
                this.lists = new List<int>[count];
                for (int i = 0; i < count; i++)
                    this.lists[i] = new List<int>();
            }
            public GraphBuilder(int count, IEnumerable<int[]> arrays) : this(count)
            {
                foreach (var item in arrays)
                    this.Add(item[0], item[1]);
            }
            public void Add(int from, int to)
            {
                this.lists[from].Add(to);
                this.lists[to].Add(from); // 有向の場合は消す
            }
            public int[][] ToArray()
            {
                var N = this.lists.Length;
                var res = new int[N][];
                for (int i = 0; i < N; i++)
                    res[i] = this.lists[i].ToArray();
                return res;
            }
        }

        static IEnumerable<T[]> Enumerate<T>(IReadOnlyCollection<T> items)
        {
            if (items.Count == 1)
            {
                yield return new T[] { items.First() };
                yield break;
            }
            foreach (var item in items)
            {
                var ret = new T[items.Count];
                ret[0] = item;
                var nokori = new HashSet<T>(items);
                nokori.Remove(item);
                foreach (var right in Enumerate(nokori))
                {
                    right.CopyTo(ret, 1);
                    yield return ret;
                }
            }
        }

        #region いつもの
#pragma warning disable
        private ConsoleReader consoleReader;
        public Program(ConsoleReader consoleReader) { this.consoleReader = consoleReader; }
        static void Main() => Console.WriteLine(new Program(new ConsoleReader(Console.In)).Calc()); static string AllLines<T>(IEnumerable<T> source) => string.Join("\n", source);
    }
    static class Ext
    {
        public static Dictionary<TKey, int> GroupCount<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, g => g.Count());
        public static Dictionary<TKey, int> GroupCount<TKey>(this IEnumerable<TKey> source) => source.GroupCount(i => i);
    }
    public class ConsoleReader { private string[] ReadLineSplit() => textReader.ReadLine().Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries); private string[] line = Array.Empty<string>(); private int linePosition; private TextReader textReader; public ConsoleReader(TextReader tr) { textReader = tr; } public int Int => int.Parse(String); public long Long => long.Parse(String); public double Double => double.Parse(String); public string String { get { if (linePosition >= line.Length) { linePosition = 0; line = ReadLineSplit(); } return line[linePosition++]; } } public class SplitLine { private string[] splited; public SplitLine(ConsoleReader cr) { splited = cr.ReadLineSplit(); cr.line = Array.Empty<string>(); } public int[] Int => String.Select(x => int.Parse(x)).ToArray(); public int[] Int0 => String.Select(x => int.Parse(x) - 1).ToArray(); public long[] Long => String.Select(x => long.Parse(x)).ToArray(); public double[] Double => String.Select(x => double.Parse(x)).ToArray(); public string[] String => splited; } public SplitLine Split => new SplitLine(this); public class RepeatReader : IEnumerable<ConsoleReader> { ConsoleReader cr; int count; public RepeatReader(ConsoleReader cr, int count) { this.cr = cr; this.count = count; } public IEnumerator<ConsoleReader> GetEnumerator() => Enumerable.Repeat(cr, count).GetEnumerator(); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerable<string> String => this.Select(cr => cr.String); public IEnumerable<int> Int => this.Select(cr => cr.Int); public IEnumerable<int> Int0 => this.Select(cr => cr.Int - 1); public IEnumerable<long> Long => this.Select(cr => cr.Long); public IEnumerable<double> Double => this.Select(cr => cr.Double); } public RepeatReader Repeat(int count) => new RepeatReader(this, count); }
    #endregion
}