# Original solution
# 写経
# https://atcoder.jp/contests/agc011/submissions/1157055

class UnionFind:
    def __init__(self, n):
        self.v = [-1 for _ in range(n)]

    def find(self, x):
        if self.v[x] < 0:
            return x
        else:
            self.v[x] = self.find(self.v[x])
            return self.v[x]

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if -self.v[x] < -self.v[y]:
            x, y = y, x
        self.v[x] += self.v[y]
        self.v[y] = x

    def root(self, x):
        return self.v[x] < 0

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def size(self, x):
        return -self.v[self.find(x)]


N, M = list(map(int, input().split()))
uf = UnionFind(2 * N)
for _ in range(M):
    u, v = list(map(int, input().split()))
    u -= 1
    v -= 1
    uf.unite(u, N + v)
    uf.unite(N + u, v)

alone = 0
bi = 0
unko = 0

for u in range(N):
    if uf.root(u) or uf.root(N + u):
        if uf.size(u) == 1:
            alone += 1
        elif uf.same(u, N + u):
            unko += 1
        else:
            bi += 1

ans = 0
ans += alone * N
ans += N * alone
ans -= alone * alone
ans += bi * bi * 2
ans += bi * unko
ans += unko * bi
ans += unko * unko

print(ans)


# Optimized solution
'''
写経
https://youtu.be/cJ-WjtA34GQ?t=1899
https://atcoder.jp/contests/agc011/submissions/1157055
http://noshi91.hatenablog.com/entry/2018/04/17/183132
https://camypaper.bitbucket.io/2016/12/18/adc2016/
'''


class UnionFind:
    def __init__(self, n):
        self.v = [-1 for _ in range(n)]  # 根(負): 連結頂点数 * (-1) / 子(正): 根の頂点番号(0-indexed)

    def find(self, x):  # xを含む木における根の頂点番号を返す
        if self.v[x] < 0:  # (負)は根
            return x
        else:  # 根の頂点番号
            self.v[x] = self.find(self.v[x])  # uniteでは, 旧根に属する頂点の根が旧根のままなので更新
            return self.v[x]

    def unite(self, x, y):  # 違う根に属していたらrankが低くなるように連結
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if -self.v[x] < -self.v[y]:  # size比較, 　(-1) * (連結頂点数 * (-1)), (正)同士の大小比較
            x, y = y, x  # 連結頂点数が少ない方をyにすると, findでの更新回数が減る？
        self.v[x] += self.v[y]  # 連結頂点数の和を取る, 連結頂点数 * (-1)
        self.v[y] = x  # 連結頂点数が少ないy(引数yの根の頂点番号)の根をx(引数xの根の頂点番号)にする

    def root(self, x):
        return self.v[x] < 0  # (負)は根

    def same(self, x, y):
        return self.find(x) == self.find(y)  # 同じ根に属するか

    def size(self, x):
        return -self.v[self.find(x)]  # 連結頂点数を返す


N, M = list(map(int, input().split()))
uf = UnionFind(2 * N)  # 全頂点 * 2(赤, 青の塗り分け)
for _ in range(M):
    u, v = list(map(int, input().split()))
    u -= 1
    v -= 1
    uf.unite(u, N + v)  # u, v: 赤で塗る / N + u, N + v: 青で塗る
    uf.unite(N + u, v)  # 隣り合う頂点を赤, 青または青, 赤で着色したものとして, 集合に加える(二部グラフならば矛盾※が出ない)

    # print(uf.v)

alone = 0
bi = 0
unko = 0

for u in range(N):
    if uf.root(u) or uf.root(N + u): # 根になりうる場合, 単独/二部はどちらもTrue, 二部グラフではない場合は, どちらかの頂点がTrue
        if uf.size(u) == 1: # 単独ならu, N + uのどちらも単独なので, 片方調べればよい
            alone += 1
        elif uf.same(u, N + u):  # ※同じ頂点の赤, 青が同じ集合にあれば塗り分けについて矛盾しており, 二部グラフではない
            unko += 1
        else:
            bi += 1  # 二部グラフ

ans = 0
ans += alone * N
ans += N * alone
ans -= alone * alone
ans += bi * bi * 2
ans += bi * unko
ans += unko * bi
ans += unko * unko

print(ans)