#include <bits/stdc++.h>
using namespace std;
const int NMAX = 40;
const int DMAX = 20;
long long adj[NMAX], dp[1 << DMAX];
int par[NMAX], fth[NMAX];
vector<int> edg[NMAX];
void dfs(int x, int p) {
  par[x] = p;
  for (int y : edg[x])
    if (!par[y]) dfs(y, 1 + 2 - p);
}
int getRoot(int x) {
  while (fth[x] >= 0) x = fth[x];
  return x;
}
bool unite(int x, int y) {
  x = getRoot(x);
  y = getRoot(y);
  if (x == y) return false;
  if (fth[x] > fth[y]) swap(fth[x], fth[y]);
  fth[x] += fth[y];
  fth[y] = x;
  return true;
}
int main(void) {
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int x, y;
    cin >> x >> y;
    --x;
    --y;
    edg[x].push_back(y);
    adj[x] |= (1LL << y);
    edg[y].push_back(x);
    adj[y] |= (1LL << x);
  }
  long long tot;
  {
    long long v = 1;
    for (int i = 0; i < n; ++i) v *= 2;
    tot = v;
  }
  long long not2;
  {
    if (n <= DMAX) {
      long long nr = 0;
      for (int msk = 0; msk < (1 << n); ++msk) {
        bool ok = true;
        for (int x = 0; x < n and ok; ++x)
          if (((msk >> x) & 1) and (adj[x] & msk)) ok = false;
        if (ok) ++nr;
      }
      not2 = nr;
    } else {
      for (int msk = 0; msk < (1 << DMAX); ++msk) {
        bool ok = true;
        long long axm = 0;
        for (int x = 0; x < DMAX and ok; ++x) {
          if ((msk >> x) & 1) axm ^= adj[x];
          if (((msk >> x) & 1) and (adj[x] & msk)) ok = false;
        }
        if (ok) dp[msk] = 1;
      }
      for (int d = 0; d < DMAX; ++d)
        for (int msk = 0; msk < (1 << DMAX); ++msk)
          if ((msk >> d) & 1) dp[msk] += dp[msk ^ (1 << d)];
      long long nr = 0;
      for (int msk = 0; msk < (1 << (n - DMAX)); ++msk) {
        bool ok = true;
        for (int x = 0; x < n - DMAX and ok; ++x)
          if (((msk >> x) & 1) and ((adj[x + DMAX] >> DMAX) & msk)) ok = false;
        if (ok) {
          int axm = (1 << DMAX) - 1;
          for (int x = 0; x < n - DMAX; ++x)
            if ((msk >> x) & 1) axm &= ~adj[x + DMAX];
          nr += dp[axm];
        }
      }
      not2 = nr;
    }
  }
  long long not0;
  not0 = not2;
  long long not1;
  {
    int nr = n;
    for (int i = 0; i < n; ++i) fth[i] = -1;
    for (int x = 0; x < n; ++x)
      for (int y : edg[x]) nr -= unite(x, y);
    long long v = 1;
    for (int i = 0; i < nr; ++i) v *= 2;
    not1 = v;
  }
  long long not01;
  {
    int nr = 0;
    for (int i = 0; i < n; ++i)
      if (edg[i].empty()) ++nr;
    long long v = 1;
    for (int i = 0; i < nr; ++i) v *= 2;
    not01 = v;
  }
  long long not02;
  {
    int nr = 0;
    for (int i = 0; i < n; ++i)
      if (!par[i]) dfs(i, 1), ++nr;
    bool ok = true;
    for (int x = 0; x < n; ++x)
      for (int y : edg[x])
        if (par[x] == par[y]) ok = false;
    if (!ok)
      not02 = 0;
    else {
      long long v = 1;
      for (int i = 0; i < nr; ++i) v *= 2;
      not02 = v;
    }
  }
  long long not12;
  not12 = not01;
  long long not012;
  {
    if (m == 0) {
      long long v = 1;
      for (int i = 0; i < n; ++i) v *= 2;
      not012 = v;
    } else
      not012 = 0;
  }
  long long ans = tot - not0 - not1 - not2 + not01 + not02 + not12 - not012;
  cout << ans << endl;
  return 0;
}
