#include<bits/stdc++.h>
using namespace std;
int n,m;
const int MOD = 1e9+7;
int g[3000][3000];
int jy[3000];
int path[3000][3000];
vector<int> to[500005];
long long ans = 0;
pair<int,int> doubleedges[1000005];
int gg[3000][3000]; //protected subgraph
bool vis[3000];
long long countpath = 0;
void search(int now,int to){ //countpath on g
	if(now==to){
		countpath++;
		return;
	}
	vis[now] = true;
	for(int i = 1;i <= n;i++){
		if((!vis[i])&&g[now][i]==1) search(i,to);
	}
	vis[now] = false;
}
bool linked = false;
void search2(int now,int to){ //linked on gg
	if(now==to||linked){
		linked = true;
		return;
	}
	vis[now] = true;
	for(int i = 1;i <= n;i++){
		if((!vis[i])&&gg[now][i]==1) search2(i,to);
	}
	vis[now] = false;
}
bool chkgg(){ //check if gg satisfies connection
	//all selected vertex gg must be connected
	//each pair of selected vertex should be connected in two different ways
	bool flag = false;
	for(int i = 1;i <= n;i++){
		if(jy[i]==1) flag = true;
		for(int j = i+1;j <= n;j++){
			if(jy[i]==1&&jy[j]==1){
				//i,j connected in gg or two different ways in g
				countpath=0,linked=false;
				memset(vis,false,sizeof(vis));
				search(i,j);
				memset(vis,false,sizeof(vis));
				search2(i,j);
				if(countpath<2&&(!linked)) return false;	
			}
		}
	}
	if(flag) return true;
	else return false;
}
void smalldfsedge(int r){
	if(r>m){
		if(chkgg()){
			/*cout << "JY: "; 
			for(int i = 1;i <= n;i++){
				if(jy[i]) cout << i << ' ';
			}
			countpath=0,linked=false;
			memset(vis,false,sizeof(vis));
			search(1,3);
			memset(vis,false,sizeof(vis));
			search2(1,3);
			cout << endl;
			for(int i = 1;i <= n;i++){
				for(int j = i+1;j <= n;j++){
					cout << i << ' ' << j << ' ' << gg[i][j] << endl;
				}
			}
			//cout << "countpath(1,3):" << countpath << endl;
			cout << "----------" << endl;*/
			ans = (ans+1)%MOD;	
		}
		return;
	}
	int u = doubleedges[r].first, v = doubleedges[r].second;
	gg[u][v] = gg[v][u] = 1;
	smalldfsedge(r+1);
	gg[u][v] = gg[v][u] = 0;
	smalldfsedge(r+1);
}
void smalldfs(int u){
	//enumerate put jy or not
	if(u>n){
		/*for(int i = 1;i <= n;i++){
			cout << jy[i] << ' ';
		}
		cout << endl;*/
		smalldfsedge(1);
		return;
	}
	jy[u] = 1;
	smalldfs(u+1);
	jy[u] = 0;
	smalldfs(u+1);
}
int main(){
	#ifndef LOCAL
	freopen("barrack.in","r",stdin);
	freopen("barrack.out","w",stdout);
	#endif
	ios::sync_with_stdio(0);
	cin >> n >> m;
	if(n<=8&&m<=10){
		//small case
		memset(g,0,sizeof(g));
		for(int i = 1;i <= m;i++){
			int u,v;
			cin >> u >> v;
			doubleedges[i] = make_pair(u,v);
			g[u][v] = g[v][u] = 1;
		}
		smalldfs(1);
		cout << ans;
	}else if(m==n-1){ //tree
		bool A = true;
		for(int i = 1;i <= m;i++){
			int u,v;
			cin >> u >> v;
			doubleedges[i] = make_pair(u,v);
			to[u].push_back(v);
			to[v].push_back(u);
			if(!((u==i&&v==i+1)||(u==i+1&&v==i))) A = false;
		}
		if(A){ // chain
			
		}
	}
	return 0;
}