// 二部グラフ判定

#include <bits/stdc++.h>
using namespace std;
using lint = long long int;
using pint = pair<int, int>;
using plint = pair<lint, lint>;
struct fast_ios { fast_ios(){ cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(20); }; } fast_ios_;
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)
template<typename T> istream& operator>>(istream &is, vector<T> &vec){ for (auto &v : vec) is >> v; return is; }
template<typename T> ostream& operator<<(ostream &os, vector<T> &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> ostream& operator<<(ostream &os, set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T1, typename T2> ostream& operator<<(ostream &os, pair<T1, T2> &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; }
template<typename TK, typename TV> ostream& operator<<(ostream &os, map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
#define dbg(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ") " << __FILE__ << endl;

// 無向グラフ

struct UndirectedGraph
{
    using pint = pair<int, int>;

    int V, E;

    vector<vector<pint>> to; // to[v1] = [pair(v2, edgeId)]
    vector<pint> edges; // edges[edgeId] = (v1, v2)

    UndirectedGraph(): V(0), E(0) {}
    UndirectedGraph(int V): V(V), E(0)
    {
        to.resize(V);
    }

    void add_edge(int v1, int v2)
    {
        to[v1].push_back(pint(v2, E));
        to[v2].push_back(pint(v1, E));
        edges.push_back(pint(v1, v2));
        E++;
    }

    // v0の連結成分からなる部分グラフが2部グラフかどうか判定
    vector<int> bip_color; // 2部グラフ判定彩色 1, 2で塗る
    vector<bool> bip_visited;
    bool is_subgraph_bipartite(int v0)
    {
        bip_color.resize(V);
        bip_visited.resize(V);
        if (!bip_color[v0]) bip_color[v0] = 1;
        queue<int> vs_pending;
        vs_pending.push(v0);
        while (!vs_pending.empty())
        {
            int now = vs_pending.front();
            vs_pending.pop();
            if (bip_visited[now]) continue;

            bip_visited[now] = true;
            for (auto nxt : to[now])
            {
                if (bip_color[nxt.first] == bip_color[now]) return false;
                else if (bip_color[nxt.first] == 0)
                {
                    bip_color[nxt.first] = 3 - bip_color[now];
                    vs_pending.push(nxt.first);
                }
            }
        }

        return true;
    }
};


struct UnionFind // UnionFind Tree (0-indexed)
{
    vector<int> par, rank;
    UnionFind(int N) : par(N), rank(N) { REP(i, N) par[i] = i; }
    int find(int x) { return (par[x] == x) ? x : (par[x] = find(par[x])); }
    void unite(int x, int y) {
        x = find(x), y = find(y); if (x == y) return;
        if (rank[x] < rank[y]) par[x] = y; else par[y] = x;
        if (rank[x] == rank[y]) rank[x]++;
    }
    bool same(int x, int y) { return find(x) == find(y); }
};


int main()
{
    int N, M;
    cin >> N >> M;

    UndirectedGraph graph(N);
    UnionFind uf(N);
    REP(_, M)
    {
        int u, v;
        cin >> u >> v;
        graph.add_edge(u - 1, v - 1);
        uf.unite(u - 1, v - 1);
    }

    map<int, lint> subtreesz;
    REP(i, N) subtreesz[uf.find(i)]++;

    lint nibu = 0, notnibu = 0, botti = 0;

    for (auto pa : subtreesz)
    {
        if (pa.second == 1)
        {
            botti++;
        }
        else if (graph.is_subgraph_bipartite(pa.first)) nibu++;
        else notnibu++;
    }

    lint ans = botti * N * 2 - botti * botti + (nibu + notnibu) * (nibu + notnibu) + nibu * nibu;
    cout << ans << endl;
}


Measured memory_bytes: 13808