#include "bits/stdc++.h"
using namespace std;

using ll = int64_t;
using vi = vector<int>;
using vb = vector<bool>;

using si = set<int>;

#define pb push_back

#define ist insert

#define sz(x) int((x).size())

#define ice(i, a, b) for (int (i) = (a); (i) < (b); ++(i))

vector<si> adj(20);
vi comp, colors(20, -1); vb done(20);
ll ans = 1, temp = 0;

void check() {
    bool ok = true;
    ice(i, 0, sz(comp)) {
        ice(j, i + 1, sz(comp)) {
            if (adj[comp[i]].count(comp[j])) {
                ok &= (colors[i] != colors[j]);
            }
            if (!ok) {
                return;
            }
        }
    }
    temp++;
}

void color(int idx) {
    if (idx == sz(comp)) {
        check();
        return;
    }
    if (!idx) {
        colors[0] = 0;
        color(1);
        colors[0] = -1;
        colors[0] = 1;
        color(1);
        colors[0] = -1;
        colors[0] = 2;
        color(1);
        colors[0] = -1;
    }
    else {
        ice(i, 0, idx) {
            if (adj[comp[idx]].count(comp[i])) {
                if (colors[i] != 0) {
                    colors[idx] = 0;
                    color(idx + 1);
                    colors[idx] = -1;
                }
                if (colors[i] != 1) {
                    colors[idx] = 1;
                    color(idx + 1);
                    colors[idx] = -1;
                }
                if (colors[i] != 2) {
                    colors[idx] = 2;
                    color(idx + 1);
                    colors[idx] = -1;
                }
                return;
            }
        }
    }
}

void cnt() {
    if (ans) {
        color(0);
    }
    ans *= temp; temp = 0;
}

void dfs(int n) {
    if (done[n]) {
        return;
    }
    done[n] = true;
    comp.pb(n);
    for (int m : adj[n]) {
        dfs(m);
    }
}

void solve() {
    int n, m; cin >> n >> m;
    ice(i, 0, m) {
        int a, b; cin >> a >> b; a--; b--;
        adj[a].ist(b); adj[b].ist(a);
    }
    ice(i, 0, n) {
        if (!done[i]) {
            dfs(i);
            cnt();
            vi().swap(comp);
            vi(20, -1).swap(colors);
        }
    }
    cout << ans;
}

int main() {
    int tc = 1;
    ice(i, 0, tc) {
        solve();
    }
}
//                        YATIN KWATRA

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define ll                      long long
#define ar                      array
#define sz(v)                   (int)(v.size())
#define inf                     1e18
#define int                     ll
#define FIO                     ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define ld                      long double
#define ull                     unsigned long long
#define endl                    "\n"
#define fo(i,a,b)               for(int i = a; i<=b ; i++)
#define rfo(i,a,b)              for(int i = a; i>=b ; i--)
#define vii                     vector<int>
#define pq                      priority_queue
#define uomii                   unordered_map<int,int,best_hash>
#define all(v)                  v.begin(),v.end()
#define mp                      make_pair
#define pb                      push_back
#define pob                     pop_back
#define ff                      first
#define ss                      second
#define pii                     pair<int,int>
#define mii                     map<int,int>
#define vvii                    vector<vii>
#define mod                     1000000007
#define MIN                     -1e9
#define pi                      3.1415926535897932384626433832795
#define cz(x)                   63 - __builtin_clzll(x)

using namespace std;
using namespace __gnu_pbds;
template<class T> using oset =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;


struct best_hash {
	static uint64_t splitmix64(uint64_t x) {

		x += 0x9e3779b97f4a7c15;
		x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
		x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
		return x ^ (x >> 31);
	}

	size_t operator()(uint64_t x) const {
		static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
		return splitmix64(x + FIXED_RANDOM);
	}
};

void INPUT()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
}

/*
----------------------------------------------------------------
   -> Check For Overflows
   -> Out of Bounds
   -> Initialisations of global arrays and variables
----------------------------------------------------------------
*/

const int N = 20;
vii v[N];
int jude[N][N];
int col[N];
bool found;

void dfs(int node, int par, int c) {
	col[node] = c;
	for (auto &i : v[node]) {
		if (found) return;
		if (i == par or col[i] == 3) continue;
		if (!col[i]) dfs(i, node, 3 - c);
		else if (col[i] == c) {
			found = 1;
			return;
		}
	}
}
int n;

bool valid(int mask) {

	fo(i, 0, n - 1) {
		fo(j, i + 1, n - 1) {
			if (mask & (1 << i) and mask & (1 << j) and jude[i][j]) return 0;
		}
	}
	return 1;
}

void solve()
{
	int m;
	cin >> n >> m;
	while (m--) {
		int x, y;
		cin >> x >> y;
		x--, y--;
		jude[x][y] = jude[y][x] = 1;
		v[x].pb(y);
		v[y].pb(x);
	}

	int ans = 0;

	fo(mask, 0, (1 << n) - 1) {
		if (!valid(mask)) continue;

		fo(i, 0, n - 1) {
			if (mask & (1 << i)) col[i] = 3;
			else col[i] = 0;
		}
		int cnt = 1;
		fo(i, 0, n - 1) {
			if (!col[i]) {
				found = 0;
				dfs(i, i, 1);
				if (found) {
					cnt = 0;
					break;
				}
				else cnt *= 2;
			}
		}
		ans += cnt;
	}

	cout << ans;
}

signed main() {

	FIO
	INPUT();

	int t;
	t = 1;
	//cin >> t;
	fo(i, 0, t - 1) {
		solve();
	}
	return 0;
}
