#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <tuple>
#include <cstdint>
#include <cstdio>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <cctype>
#include <climits>

#define rep(i, n) for(int i = 0; i < n; i++)
#define per(i, n) for(int i = n - 1; i >= 0; i--)
using ll = long long;
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define pii pair<int, int>
#define pll pair<ll, ll>
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define mod 1000000007
using namespace std;
template<class T, class U>
T &chmax(T &a, const U &b){ if(a < b) a = b; return a; }
template<class T, class U>
T &chmin(T &a, const U &b){ if(a > b) a = b; return a; }
int n,m;
vvi root;
vi visited;
//woutの頂点を通らずにposからたどれる場所を見る
void fill(int pos, vi &checked){
  if(checked[pos] != -1) return;
  checked[pos] = 1;
  for(int x : root[pos]){
    if(checked[x] != -1) continue;
    fill(x, checked);
  }
}
ll dfs(int pos, vi checked){
  vi cnt(3);
  for(int x : root[pos]){
    if(checked[x] == -1) continue;
    cnt[checked[x]]++;
  }
  ll ans = 0;
  rep(i, 3){
    if(cnt[i]) continue;
    checked[pos] = i;
    ll res = 1;
    vi temp = checked;
    for(int x : root[pos]){
      if(checked[x] != -1 || temp[x] != -1) continue;
      fill(x, temp);
      ll num = dfs(x, checked);
      res *= num;
    }
    ans += res;
  }
  return ans;
}

int main(){
  cin >> n >> m;
  root.resize(n);
  rep(i, m){
    int a,b;
    cin >> a >> b;
    a--; b--;
    root[a].push_back(b);
    root[b].push_back(a);
  }
  visited.resize(n, -1);
  ll ans = 1;
  rep(i, n){
    if(visited[i] != -1) continue;
    fill(i, visited);
    ll num = dfs(i, vi(n, -1));
    ans *= num;
    if(!ans) break;
  }
  cout << ans << "\n";
}
#include <bits/stdc++.h>

using namespace std;

vector<int> a[27];
int used[27], color[27];
vector< pair<int,int> > t;

long long n,m,v1,v2,res,globalres;

void dfs(int v,int type) {
    used[v]=type;
    t.push_back({v,used[v]});
    for(auto to : a[v])
        if(used[to] == 0) dfs(to,2);
}

void put(int pos, int col) {
    int v = t[pos].first;
    for(auto to : a[v])
        if(color[to]==col) return;
    if(pos==n-1 || t[pos+1].second==1) res++;
    else {
        color[v] = col;
        put(pos+1, 1);
        put(pos+1, 2);
        put(pos+1, 3);
        color[v] = 0;
    }
}


int main() {
    cin >> n >> m;
    for(int i=1; i<=m; i++) {
        cin >> v1 >> v2;
        a[v1].push_back(v2);
        a[v2].push_back(v1);
    }

    for(int i=1; i<=n; i++)
        if(used[i]==0) {
            used[i]=1;
            dfs(i,1);
        }
    globalres = 1;
    for(int i=0; i<n; i++)
        if(t[i].second==1) {
            res = 0;
            put(i,1);
            put(i,2);
            put(i,3);
            globalres *= res;
        }
    cout << globalres << endl;
    return 0;
}
