#include <bits/stdc++.h>
using namespace std;
 
// #include <ext/pb_ds/assoc_container.hpp> 
// #include <ext/pb_ds/tree_policy.hpp> 
// using namespace __gnu_pbds; 
// typedef tree<ll, null_type, less_equal<ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set; 
 
#define pb push_back
#define S second
#define F first
#define FAST ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define vll vector<long long int>
#define vld vector<long double>
#define pll pair<long long int,long long int>
/* unordered_map<int,int>mp; mp.reserve(1024); mp.max_load_factor(0.25); */
#define mod 1000000007
#define mod2 998244353
#define ll long long int
#define ld long double
#define pi 3.141592653589793238
#define Endl endl
#define endl "\n"
const int N = 1e2 + 15;
const ll inf = 1e18;

vll a[N];
ll ans = 1;
vll done(N);
ll limit;
vll comp;
vll color(N);
void dfs(ll u)
{
        done[u] = true;
        for(auto v:a[u])
        {
                if(!done[v])
                        dfs(v);
        }
        comp.pb(u);
}

ll recur(ll idx)
{
        if(idx == limit)
                return 1ll;
        ll u = comp[idx];
        ll ans = 0;
        for(ll col = 0; col < 3; col++)
        {
                bool chk = true;
                for(auto v:a[u])
                {
                        if(color[v] == col)
                                chk = false;
                }
                if(chk)
                {
                        color[u] = col;
                        ans += recur(idx+1);
                        color[u] = -1;
                }
        }
        return ans;
}

void solve()
{
        ll n , m;
        cin >> n >> m;
        for(ll i=1;i<=m;i++)
        {
                ll u,v;
                cin >> u >> v;
                a[u].pb(v);
                a[v].pb(u);
        }
        ll ret = 1;
        for(ll i=1;i<=n;i++)
        {
                if(done[i] == 0)
                {
                        comp.clear();
                        dfs(i);
                        reverse(comp.begin(),comp.end());
                        limit = comp.size();
                        for(ll i=0;i<N;i++)
                                color[i] = -1;
                        ret *= recur(0);
                }
        }
        cout << ret;
}
 
void debug(ll tt) {}
 
signed main()
{
        FAST;
        ll t = 1;
        // cin >> t;
        while(t--)
        {
                solve();
        }
}
// freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
// D - RGB Coloring 2
// sample code
// reference: https://atcoder.jp/contests/abc199/submissions/22053625
#include <bits/stdc++.h>
using namespace std;
#define vec vector
using vi = vec<int>;
using ll = int64_t;
#define rep(i,e) for(int i=0;i<(e);++i)

vec<vi> G;
vi IX; //dfs の順を記録。違う連結成分になら同じ index もある

ll dfs(int now, vi&v){
	for(int to:G[now]) if(v[to] == v[now]) return 0;
	ll res = 1;
	for(int to:G[now]){
		if(IX[to] == -1) IX[to] = IX[now] + 1;
		if(IX[to] == IX[now] + 1){
			ll tmp = 0;
			v[to] = (v[now] + 1) % 3;
			tmp += dfs(to, v);
			v[to] = (v[now] + 2) % 3;
			tmp += dfs(to, v);
			v[to] = -1;
			res *= tmp;
			if (tmp == 0) break;
			// tmp == 0 の時、早期に return してるので
			// IX が振り切れていない事に注意
		}
	}
	return res;
}


int main(){
	int n, m; cin>>n>> m;
	G.resize(n);
	rep(i, m){
		int a, b; cin>>a>>b; --a, --b;
		G[a].push_back(b);
		G[b].push_back(a);
	}

	IX.resize(n, -1);
	vi v(20, -1);
	ll ans = 1;
	rep(i, n){
		if(IX[i] != -1) continue;
		IX[i] = v[i] = 0;
		ans *= dfs(i, v) * 3;
	}
	cout<< ans <<endl;
}
