#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
inline int read(){
	int n = 0, f = 1;
	char ch = getchar();
	while(!isdigit(ch)){
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while(isdigit(ch)){
		n *= 10, n += ch ^ 48;
		ch = getchar();
	}
	return n * f;
}
void Mod(int &x){
	if(x >= mod) x -= mod;
}
int n, m, head[500001], cnt, ch[500001], chcnt, start, viscnt, vis[500001], ans;
struct edge{
	int to, next;
}e[2000001];
void add(int u, int v){
	e[++cnt].to = v;
	e[cnt].next = head[u];
	head[u] = cnt;
}
struct ori{
	int u, v;
}eg[1000001];
void check(int u){
	vis[u] = 1;
	if(ch[u]) viscnt++;
	for(int i = head[u]; i; i = e[i].next){
		int v = e[i].to;
		if(vis[v]) continue;
		check(v);
	}
}
int main(){
	freopen("barrack.in", "r", stdin);
	freopen("barrack.out", "w", stdout);
	n = read(), m = read();
	for(int i = 1; i <= m; i++){
		eg[i].u = read(), eg[i].v = read();
	}
	for(int i = 1; i < (1 << n); i++){
		chcnt = 0;
		memset(ch, 0, 4 * (n + 1));
		for(int k = 0; k < n; k++){
			if(i & (1 << k)){
				start = k + 1;
				ch[k + 1] = 1;
				chcnt++;
			}
		}
		for(int j = 0; j < (1 << m); j++){
			cnt = 0;
			memset(head, 0, 4 * (n + 1));
			for(int k = 0; k < m; k++){
				if(j & (1 << k)){
					add(eg[k + 1].u, eg[k + 1].v);
					add(eg[k + 1].v, eg[k + 1].u);
				}
			}
			viscnt = 0;
			memset(vis, 0, 4 * (n + 1));
			check(start);
			if(viscnt == chcnt) ans++, Mod(ans);
		}
	}
	printf("%d", ans);
	return 0;
}
/*
三回啊三回 
//freopen
freeopen
feropen
freopen("barrack.in", "w", stdout);
freopen("barrack.out", "r", stdin);

感觉像割边，但是想不下去了 
打了个O(2^(n+m))的究极暴力以后发现题目看错了，把袭击一条道路看成多条，伤心 
期望得分0 
*/
