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

typedef long long int ll;
#define endl "\n"
#define pll pair<ll,ll>
#define pii pair<int ,int>
#define pb push_back
#define vi vector<int>
#define vl vector<ll>
#define vpii vector<pair<int, int>>
#define mems(x,y) memset(x,y,sizeof(x))
#define all(x) (x).begin(),(x).end()
#define forn(i,s,e) for(int i = s; i < (e); ++i)
#define FASTIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define FILEIO                          \
freopen("./input.txt", "r", stdin); \
freopen("./output.txt", "w", stdout);
#define debug(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#define time__(d)                                                   \
for (                                                                   \
auto blockTime = make_pair(chrono::high_resolution_clock::now(), true); \
        blockTime.second;                                               \
debug("%s : %lld ms\n ", d, chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - blockTime.first).count()), blockTime.second = false)
const int M = 1e9 + 7;

template <class T> T ABS(const T &x) {return x>0? x:-x;}
ll gcd(ll n1, ll n2) {return n2==0? ABS(n1) : gcd(n2,n1%n2);}
ll lcm(ll n1, ll n2) {return n1==0 && n2==0? 0 : ABS(n1*n2)/gcd(n1,n2);}
ll ceil2(ll a, ll b) {return (a + b - 1) / b;}

// int dx[4] = {1,-1,0,0};
// int dy[4] = {0,0,1,-1};

int main()
{
FASTIO
#ifdef LOCAL
FILEIO
#endif
    int n,m;
    cin >> n >> m;
    vector<unsigned> to(n);

    while(m--){
        int a,b;
        cin >> a >> b;
        --a,--b;
        to[a] |= 1 << b;
        to[b] |= 1 << a;
    }

    vector<unsigned> cs(3);
    ll res = 0;
    auto dfs = [&](auto &&self, int curr) -> void {
        if(curr == n){
            ++res;
            return;
        }
        if(to[curr] == 0){
            self(self,curr+1);
        }
        else{
            forn(i,0,3){
                cs[i] += 1 << curr;
                if((to[curr] & cs[i]) == 0) self(self, curr+1);
                cs[i] -= 1 << curr;
            }
        }
    };
    dfs(dfs,0);
    for(auto j : to) if(!j) res *= 3;
    cout << res << endl;
    return 0;
}
#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define FOR(i,n,m) for(int i=(int)(n); i<=(int)(m); i++)
#define RFOR(i,n,m) for(int i=(int)(n); i>=(int)(m); i--)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define RITR(x,c) for(__typeof(c.rbegin()) x=c.rbegin();x!=c.rend();x++)
#define setp(n) fixed << setprecision(n)

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

#define ll long long
#define vll vector<ll>
#define vi vector<int>
#define pll pair<ll,ll>
#define pi pair<int,int>

#define all(a) (a.begin()),(a.end())
#define rall(a) (a.rbegin()),(a.rend())
#define fi first
#define se second
#define pb push_back
#define ins insert

#define debug(a) cerr<<(a)<<endl
#define dbrep(a,n) rep(_i,n) cerr<<(a[_i])<<" "; cerr<<endl
#define dbrep2(a,n,m) rep(_i,n){rep(_j,m) cerr<<(a[_i][_j])<<" "; cerr<<endl;}

using namespace std;

template<class A, class B>
ostream &operator<<(ostream &os, const pair<A,B> &p){return os<<"("<<p.fi<<","<<p.se<<")";}
template<class A, class B>
istream &operator>>(istream &is, pair<A,B> &p){return is>>p.fi>>p.se;}

template<class T>
vector<T> make_vec(size_t a){
	return vector<T>(a);
}
template<class T, class... Ts>
auto make_vec(size_t a, Ts... ts){
	return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}

/* Some Libraries */

//-------------------------------------------------

int main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N,M; cin>>N>>M;

    vector<vi> G(N);
    rep(i,M){
        int a,b; cin>>a>>b; a--; b--;
        G[a].pb(b);
        G[b].pb(a);
    }

    vector<bool> seen(N);
    auto dfs = [&](auto &dfs, vi &vec, int v)->void{
        seen[v] = true;
        vec.pb(v);
        for(auto u:G[v]){
            if (seen[u]) continue;
            dfs(dfs,vec,u);
        }    
    };

    ll ans=1;
    rep(v,N)if(!seen[v]){
        vi vec;
        dfs(dfs,vec,v);
        int sz = vec.size();
        
        ll sum=0;
        vi color(N,-1);
        auto dfs2 = [&](auto &dfs, int idx)->void{
            if (idx==sz){
                sum+=3;
                return;
            }
            const int &v = vec[idx];
            if (idx==0){
                color[v]=0;
                dfs(dfs,idx+1);
                color[v]=-1;
                return;
            }
            int mask=0b111;
            for(auto u:G[v]){
                if (color[u]==-1) continue;
                mask &= ~(1<<color[u]);
            }
            rep(i,3)if(mask>>i&1){
                color[v]=i;
                dfs(dfs,idx+1);
                color[v]=-1;
            }
        };
        dfs2(dfs2,0);
        ans*=sum;
    }
    cout<<ans<<"\n";
    return 0;
}
