#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include <queue>
#include <deque>
#include <bitset>
#include <iterator>
#include <list>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <numeric>
#include <utility>
#include <iomanip>
#include <limits>
#include <time.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
 
#define debug(x) cout << #x << " = " << x << endl
#define fori(i, ini, lim) for(int i = int(ini); i < int(lim); i++)
#define ford(i, ini, lim) for(int i = int(ini); i >= int(lim); i--)
 
using namespace std;
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;
 
const int MAX = 20;
bool visited[MAX];
int adj[MAX];
int n, m;

vector<int> bfs(int source) {
    queue<int> q;
    q.push(source);
    visited[source] = true;
    vector<int> touched;
    while (!q.empty()) {
        int cur = q.front();
        q.pop();
        touched.push_back(cur);
        fori (i, 0, n) {
            if (adj[cur] & (1 << i)) {
                if (!visited[i]) {
                    visited[i] = true;
                    q.push(i);
                }
            }
        }
    }
    return touched;
}

int cant[3];
void roll(const vector<int> &v, int idx, ll &total) {
    if (idx == (int) v.size()) {
        total++;
        return;
    }
    int k = v[idx];
    fori (i, 0, 3) {
        if (cant[i] & (1 << k)) continue;
        int prv_cant = cant[i];
        cant[i] |= adj[k];
        roll(v, idx + 1, total);
        cant[i] = prv_cant;
    }
}

ll calc(const vector<int> &v) {
    ll total = 0;
    roll(v, 0, total);
    return total;
}

void solve() {
    cin >> n >> m;
    fori (i, 0, m) {
        int x, y;
        cin >> x >> y;
        x--, y--;
        adj[x] |= 1 << y;
        adj[y] |= 1 << x;
    }
    ll ans = 1;
    fori (i, 0, n) {
        if (!visited[i]) {
            vector<int> v = bfs(i);
            ans *= calc(v);
        }
    }
    cout << ans << endl;
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    solve();
    return 0;
}

#include <bits/stdc++.h>
#define speed                   \
  ios_base::sync_with_stdio(0); \
  cin.tie(0);                   \
  cout.tie(0);
#define precision     \
  cout.precision(30); \
  cerr.precision(10);
#define ll long long
#define ld long double
#define pll pair<ll, ll>
#define pii pair<int, int>
#define forn(n) for (int i = 1; i <= n; i++)
#define forlr(l, r) for (int i = l; i != r; (l > r ? i-- : i++))
#define pb(x) push_back(x)
#define sz(x) (int)x.size()
#define mp(x, y) make_pair(x, y)
#define all(x) x.begin(), x.end()
#define pc(x) __builtin_popcount(x)
#define pcll(x) __builtin_popcountll(x)
#define F first
#define S second
using namespace std;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
void ioi(string name) {
  freopen((name + ".in").c_str(), "r", stdin);
  freopen((name + ".out").c_str(), "w", stdout);
}
ll n, m, e, k = 1, a[25];
vector<ll> t, g[25];
bitset<25> w;
void dfs(ll v) {
  t.pb(v);
  w[v] = 1;
  for (auto to : g[v])
    if (!w[to]) dfs(to);
}
void kek(ll v = 0) {
  if (sz(t) <= v) {
    e++;
    return;
  }
  ll x = t[v];
  for (int i = 1; i <= 3; i++) {
    ll ok = 1;
    for (auto j : g[x])
      if (a[j] == i) goto bruh;
    a[x] = i;
    kek(v + 1);
    a[x] = 0;
  bruh:;
  }
}
int main() {
  speed;
  precision;
  // code
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    ll u, v;
    cin >> u >> v;
    g[u].pb(v);
    g[v].pb(u);
  }
  for (int i = 1; i <= n; i++) {
    if (w[i]) continue;
    t.clear();
    dfs(i);
    e = 0;
    kek();
    k *= e;
  }
  cout << k;
  // endl
#ifndef ONLINE_JUDGE
  cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
  return 0;
}