#include <bits/stdc++.h>

using namespace std;
const int P = 1e9 + 7;


int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	freopen("barrack.in", "r", stdin);
	freopen("barrack.out", "w", stdout);
	int n, m;
	cin >> n >> m;
	vector<array<int, 2>> e(m);
	for (int i = 0; i < m; i++) {
		int x, y;
		cin >> x >> y;
		--x, --y;
		e[i] = array<int, 2>{x, y};
	}
	vector<int> p(n), sz(n);
	auto find = [&](int x) {
		while (x != p[x]) x = p[x] = p[p[x]];
		return x;
	};
	auto unite = [&](int x, int y) {
		x = find(x), y = find(y);
		if (x == y) {
			return;
		} else {
			sz[x] += sz[y];
			p[y] = x;
		}
	};
	int ans = 0;

	vector<int> tmp;
	for (int s = 1; s < (1 << n); s++) {
		vector<int> vt;
		for (int i = 0; i < n; i++) if (s >> i & 1) vt.push_back(i);
		for (int t = 0; t < (1 << m); t++) {
			bool ok = true;
			for (int c = 0; c < m; c++) if (~t >> c & 1) {
				vector<vector<int>> f(n, vector<int>(n, 0));
				for (int i = 0; i < n; i++) f[i][i] = 1;
				for (int j = 0; j < m; j++) {
					if (c != j) {
						f[e[j][0]][e[j][1]] = f[e[j][1]][e[j][0]] = 1;
					}
				}
				for (int k = 0; k < n; k++) {
					for (int i = 0; i < n; i++) {
						for (int j = 0; j < n; j++) {
							f[i][j] |= f[i][k] & f[k][j];
						}
					}
				}
				bool res = true;
				for (int i = 0; i < (int) vt.size(); i++) {
					for (int j = i + 1; j < (int) vt.size(); j++) {
						res &= f[vt[i]][vt[j]];
					}
				}
				ok &= res;
			}
			if (ok) ans += 1;
		}
	}
	cout << ans << "\n";
	return 0;
}