#include "bits/stdc++.h"
#ifdef FFS
#include "debug.h"
#else
#define debug(args...)
#endif
using namespace std;
const int N = 6 + 9 + 4e5;
vector <int> gr[N];
signed main()
{
    ios_base::sync_with_stdio(false), cin.tie(nullptr);
    int n; cin >> n;
    int x = INT_MAX, y = INT_MIN;
    for(int i = 0, a, b; i < n; ++i)
    {
        cin >> a >> b;
        x = min({x, a, b}), y = max({y, a, b});
        gr[a].emplace_back(b);
        gr[b].emplace_back(a);
    }
    bool vis[N], tree;
    int node, ans = 0;
    memset(vis, false, sizeof vis);
    function<void(int, int)> dfs = [&] (int child, int parent)
    {
        if(vis[child])
        {
            tree = false;
            return;
        }
        vis[child] = true, ++node;
        for(auto c : gr[child]) if(c ^ parent) dfs(c, child);
    };
    for(auto i = x; i <= y; ++i) 
    {
        if(gr[i].empty() or vis[i]) continue;
        tree = true, node = 0;
        dfs(i, -1);
        ans += tree ? (node - 1) : node;
    }
    cout << ans << '\n';
}
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> ii;
typedef tuple<ll, ll, ll> iii;
typedef vector<ll> vi;
typedef vector<ii> vii;
typedef vector<iii> viii;
typedef vector<vi> vvi;
typedef vector<vii> vvii;
#define REP(i,n) for (ll i = 0; i < n; ++i)
#define REPR(i,n) for (ll i = n-1; i >= 0; --i)
#define FOR(i,m,n) for (ll i = m; i < n; ++i)
#define FORR(i,m,n) for (ll i = n-1; i >= m; --i)
#define FORE(x,xs) for (const auto& x : xs)
#define FORI(i,v) for (auto i = v.begin(); i != v.end(); i++)
#define ALL(v) v.begin(), v.end()
#define SORT(v) sort(ALL(v))
#define REV(v) reverse(ALL(v))
#define UNIQ(v) sort(ALL(v)); v.erase(unique(ALL(v)),end(v))
#define CHMIN(x,y) x = min(x, y)
#define CHMAX(x,y) x = max(x, y)
#define YES(b) cout << ((b) ? "YES" : "NO") << endl
#define Yes(b) cout << ((b) ? "Yes" : "No") << endl

struct UnionFind {
private:
    int N;
    vi parent;
    vi rank_;

    void init(int n) {
        N = n;
        parent.resize(0); parent.clear(); parent.resize(n);
        REP (i, N) parent[i] = i;
        rank_.resize(0); rank_.clear(); rank_.resize(n);
    }

public:
    UnionFind() { init(0); }
    UnionFind(int n) { init(n); }

    int root(int x) {
        return (parent[x] == x) ? x : parent[x] = root(parent[x]);
    }

    bool isSame(int x, int y) {
        return root(x) == root(y);
    }

    void merge(int x, int y) {
        x = root(x);
        y = root(y);
        if (x == y) return;

        if (rank_[x] < rank_[y])
            parent[x] = y;
        else {
            parent[y] = x;
            if (rank_[x] == rank_[y]) rank_[x]++;
        }
    }
};

const int MAX = 21;

int N, M;

vi adj[MAX];
vector<bool> visited;
vector<char> colors;

char next(char c, bool s) {
    if (c == 'R') {
        if (s) return 'B';
        else return 'G';
    } else if (c == 'G') {
        if (s) return 'R';
        else return 'B';
    } else {
        if (s) return 'R';
        return 'G';
    }
}

bool check(int state, int root) {
    queue<int> q;
    q.push(root);
    while (q.size()) {
        int x = q.front(); q.pop();
        if (x == root) {
            colors[x] = 'R';
        }
        FORE (a, adj[x]) {
            if (colors[a] == 'W') {
                colors[a] = next(colors[x], (state>>a)&1);
                if (!visited[a]) q.push(a);
                visited[a] = true;
            } else {
                if (colors[a] == colors[x]) return false;
            }
        }
    }
    return true;
}

int main() {
    cout << fixed << setprecision(15);
    cin >> N >> M;
    UnionFind uf(N);
    REP (i, M) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        adj[a].push_back(b);
        adj[b].push_back(a);
        uf.merge(a, b);
    }
    vi roots;
    REP (i, N) if (uf.root(i) == i) roots.push_back(i);

    ll ans = 0;
    REP (state, 1<<N) {
        visited = vector<bool>(N, false);
        colors = vector<char>(N, 'W');
        bool f = true;
        FORE (r, roots) {
            if ((state & (1<<r)) || !check(state, r)) {
                f = false;
                break;
            }
        }
        if (f) ans++;
    }
    FORE (r, roots) ans *= 3;
    cout << ans << endl;
}
