mod = 10 ** 9 + 7
mod2 = 2 ** 61 + 1
from collections import deque
import heapq
import time
from bisect import bisect_left, insort_left, bisect_right
import sys

input = sys.stdin.readline
_NUMINT_ALL = list(range(10))


def main():
    ans = solve()

    if ans is True or ans is False:
        YesNo(ans)
    elif ans is not None:
        print(ans)


def solve():
    N, M = iip(False)

    AB = iipt(M)
    AB.reverse()
    uf = UfTree(N)

    benlist = [0]

    cur = 0
    for a, b in AB:
        a -= 1
        b -= 1
        c1 = uf.size(a)
        c2 = uf.size(b)
        uf.unite(a, b)
        if c2 != uf.size(a):
            cur += c1*c2
        benlist.append(cur)

    t = benlist.pop()
    benlist.reverse()
    #print(benlist)

    ans = [t - i for i in benlist]

    split_print_enter(ans)


#####################################################ライブラリ集ここから

def kiriage_warizan(a, b):
    return -(-a//b)


def iip(listed=True):  # 数字のinputをlistで受け取る
    d = input().rstrip("\n").split()
    try:
        ret = [int(i) for i in d]
    except:
        ret = [int(i) if i in _NUMINT_ALL else i for i in d]
        if len(ret) == 1:
            return ret[0]

    if len(ret) == 1 and not listed:
        return ret[0]
    return ret

def iipt(l, listed=False, num_only=True):  # 縦向きに並んでいるデータをリストに落とし込む(iip利用)
    ret = []
    for i in range(l):
        ret.append(iip(listed=listed))
    return ret


def saidai_kouyakusuu(A):  # 最大公約数
    l = len(A)
    while True:
        m = min(A)
        mx = max(A)
        if m == mx:
            return m

        for i in range(l):
            if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m


def make_graph_edge_flat(N):  # グラフ作成のための辺をリストで返す
    ret = []
    for i in range(N-1):
        a, b, c = iip()
        a -= 1
        b -= 1
        ret[a].append((b, c))
        ret[b].append((a, c))
    return ret


def sort_tuples(l, index):  # タプルのリストを特定のインデックスでソートする
    if isinstance(l, list):
        l.sort(key=lambda x: x[index])
        return l
    else:
        l = list(l)
        return sorted(l, key=lambda x: x[index])


def count_elements(l):  # リストの中身の個数を種類分けして辞書で返す
    d = {}
    for i in l:
        if i in d:
            d[i] += 1
        else:
            d[i] = 1
    return d


def safeget(l, index, default="exception"):  # listの中身を取り出す時、listからはみ出たり
    if index >= len(l):                      # マイナスインデックスになったりするのを防ぐ
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]))
        else:
            return default
    elif index < 0:
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
    else:
        return l[index]


def sortstr(s):  # 文字列をソートする
    return "".join(sorted(s))


def iip_ord(startcode="a"):  # 文字列を数字の列に変換する(数字と文字は1:1対応)
    if isinstance(startcode, str):
        startcode = ord(startcode)
    return [ord(i) - startcode for i in input()]


def YesNo(s):  # TrueFalseや1, 0をYesNoに変換する
    if s:
        print("Yes")
    else:
        print("No")


def fprint(s):  # リストを平たくしてprintする(二次元リストを見やすくしたりとか)
    for i in s:
        print(i)


def bitall(N):  # ビット全探索用のインデックスを出力
    ret = []
    for i in range(2 ** N):
        a = []
        for j in range(N):
            a.append(i % 2)
            i //= 2
        ret.append(a)
    return ret

def split_print_space(s):  # リストの中身をスペース区切りで出力する
    print(" ".join([str(i) for i in s]))


def split_print_enter(s):  # リストの中身を改行区切りで出力する
    print("\n".join([str(i) for i in s]))


def soinsuu_bunkai(n):  # 素因数分解
    ret = []
    for i in range(2, int(n ** 0.5) + 1):
        while n % i == 0:
            n //= i
            ret.append(i)
        if i > n:
            break
    if n != 1:
        ret.append(n)
    return ret


def conbination(n, r, mod, test=False):  # nCrをmodを使って計算する
    if n <= 0:
        return 0
    if r == 0:
        return 1
    if r < 0:
        return 0
    if r == 1:
        return n
    ret = 1
    for i in range(n - r + 1, n + 1):
        ret *= i
        ret = ret % mod

    bunbo = 1
    for i in range(1, r + 1):
        bunbo *= i
        bunbo = bunbo % mod

    ret = (ret * inv(bunbo, mod)) % mod
    if test:
        # print(f"{n}C{r} = {ret}")
        pass
    return ret


def inv(n, mod):  #  modnにおける逆元を計算
    return power(n, mod - 2)


def power(n, p, mod_=mod):  # 繰り返し二乗法でn**p % modを計算
    if p == 0:
        return 1
    if p % 2 == 0:
        return (power(n, p // 2, mod_) ** 2) % mod_
    if p % 2 == 1:
        return (n * power(n, p - 1, mod_)) % mod_


def nibutan_func(func, target, left, right, side="left"): # 関数を二分探索
    l = left
    r = right
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if func(x) == target:
            return x
        elif func(x) > target:
            r = x
        else:
            l = x

    if side == "left" or func(x) == target:
        return l
    else:
        return r


def nibutan_list(list_, target, side="left"):  # リストを二分探索
    if not isinstance(list_, list):
        list_ = list(list_)

    l = 0
    r = len(list_)
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if list_[x] == target:
            return x
        elif list_[x] > target:
            r = x
        else:
            l = x

    if side == "left" or list_[x] == target:
        return l
    else:
        return r


class UfTree():
    def __init__(self, maxnum):
        self.parent = list(range(maxnum))
        self._size = [1] * maxnum
        self.rank = [0] * maxnum

    def size(self, a):
        return self._size[self.root(a)]

    def root(self, a):
        rank = 0
        cur = a
        while True:
            if self.parent[cur] == cur:
                #for i in path: # 経路圧縮
                #    self.parent[i] = cur
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

    def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb:
            return self

        self._size[ra] += self._size[rb]
        self.parent[rb] = ra
        return self

if __name__ == "__main__":
    main() mod = 10 ** 9 + 7 mod 10 ** 9 + 7 10 ** 9 10 9 7 mod2 = 2 ** 61 + 1 mod2 2 ** 61 + 1 2 ** 61 2 61 1 from collections import deque import heapq heapq import time time from bisect import bisect_left, insort_left, bisect_right import sys sys input = sys.stdin.readline input sys.stdin.readline sys.stdin sys stdin readline _NUMINT_ALL = list(range(10)) _NUMINT_ALL list(range(10)) list range(10) range 10 def main():
    ans = solve()

    if ans is True or ans is False:
        YesNo(ans)
    elif ans is not None:
        print(ans) main ans = solve() ans solve() solve if ans is True or ans is False:
        YesNo(ans)
    elif ans is not None:
        print(ans) ans is True or ans is False ans is True ans True ans is False ans False YesNo(ans) YesNo ans elif ans is not None:
        print(ans) ans is not None ans None print(ans) print ans def solve():
    N, M = iip(False)

    AB = iipt(M)
    AB.reverse()
    uf = UfTree(N)

    benlist = [0]

    cur = 0
    for a, b in AB:
        a -= 1
        b -= 1
        c1 = uf.size(a)
        c2 = uf.size(b)
        uf.unite(a, b)
        if c2 != uf.size(a):
            cur += c1*c2
        benlist.append(cur)

    t = benlist.pop()
    benlist.reverse()
    #print(benlist)

    ans = [t - i for i in benlist]

    split_print_enter(ans)


#####################################################ライブラリ集ここから solve N, M = iip(False) N iip(False) iip False M AB = iipt(M) AB iipt(M) iipt M AB.reverse() AB.reverse AB reverse uf = UfTree(N) uf UfTree(N) UfTree N benlist = [0] benlist [0] 0 cur = 0 cur 0 for a, b in AB:
        a -= 1
        b -= 1
        c1 = uf.size(a)
        c2 = uf.size(b)
        uf.unite(a, b)
        if c2 != uf.size(a):
            cur += c1*c2
        benlist.append(cur)

     a b AB a -= 1 a 1 b -= 1 b 1 c1 = uf.size(a) c1 uf.size(a) uf.size uf size a c2 = uf.size(b) c2 uf.size(b) uf.size uf size b uf.unite(a, b) uf.unite uf unite a b if c2 != uf.size(a):
            cur += c1*c2
         c2 != uf.size(a) c2 uf.size(a) uf.size uf size a cur += c1*c2 cur c1*c2 c1 c2 benlist.append(cur) benlist.append benlist append cur t = benlist.pop() t benlist.pop() benlist.pop benlist pop benlist.reverse() benlist.reverse benlist reverse t - i for i in benlist for i in benlist i benlist for i in benlist t - i t i ans = [t - i for i in benlist] ans [t - i for i in benlist] split_print_enter(ans) split_print_enter ans def kiriage_warizan(a, b):
    return -(-a//b) kiriage_warizan return -(-a//b) -(-a//b) -a//b -a a b a a b b def iip(listed=True):  # 数字のinputをlistで受け取る
    d = input().rstrip("\n").split()
    try:
        ret = [int(i) for i in d]
    except:
        ret = [int(i) if i in _NUMINT_ALL else i for i in d]
        if len(ret) == 1:
            return ret[0]

    if len(ret) == 1 and not listed:
        return ret[0]
    return ret iip d = input().rstrip("\n").split() d input().rstrip("\n").split() ().rstrip("\n").split ().rstrip("\n") ().rstrip () input rstrip "\n" split try:
        ret = [int(i) for i in d]
    except:
        ret = [int(i) if i in _NUMINT_ALL else i for i in d]
        if len(ret) == 1:
            return ret[0]

     except:
        ret = [int(i) if i in _NUMINT_ALL else i for i in d]
        if len(ret) == 1:
            return ret[0]

     int(i) if i in _NUMINT_ALL else i for i in d for i in d i d for i in d int(i) if i in _NUMINT_ALL else i i in _NUMINT_ALL i _NUMINT_ALL int(i) int i i ret = [int(i) if i in _NUMINT_ALL else i for i in d] ret [int(i) if i in _NUMINT_ALL else i for i in d] if len(ret) == 1:
            return ret[0]

     len(ret) == 1 len(ret) len ret 1 return ret[0] ret[0] ret 0 int(i) for i in d for i in d i d for i in d int(i) int i ret = [int(i) for i in d] ret [int(i) for i in d] if len(ret) == 1 and not listed:
        return ret[0]
     len(ret) == 1 and not listed len(ret) == 1 len(ret) len ret 1 not listed listed return ret[0] ret[0] ret 0 return ret ret listed=True listed True def iipt(l, listed=False, num_only=True):  # 縦向きに並んでいるデータをリストに落とし込む(iip利用)
    ret = []
    for i in range(l):
        ret.append(iip(listed=listed))
    return ret iipt ret = [] ret [] for i in range(l):
        ret.append(iip(listed=listed))
     i range(l) range l ret.append(iip(listed=listed)) ret.append ret append iip(listed=listed) iip listed=listed listed listed return ret ret l l listed=False listed False num_only=True num_only True def saidai_kouyakusuu(A):  # 最大公約数
    l = len(A)
    while True:
        m = min(A)
        mx = max(A)
        if m == mx:
            return m

        for i in range(l):
            if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m saidai_kouyakusuu l = len(A) l len(A) len A while True:
        m = min(A)
        mx = max(A)
        if m == mx:
            return m

        for i in range(l):
            if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m True m = min(A) m min(A) min A mx = max(A) mx max(A) max A if m == mx:
            return m

         m == mx m mx return m m for i in range(l):
            if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m i range(l) range l if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m A[i] % m == 0 A[i] % m A[i] A i m 0 A[i] = m A[i] A i m A[i] %= m A[i] A i m A A def make_graph_edge_flat(N):  # グラフ作成のための辺をリストで返す
    ret = []
    for i in range(N-1):
        a, b, c = iip()
        a -= 1
        b -= 1
        ret[a].append((b, c))
        ret[b].append((a, c))
    return ret make_graph_edge_flat ret = [] ret [] for i in range(N-1):
        a, b, c = iip()
        a -= 1
        b -= 1
        ret[a].append((b, c))
        ret[b].append((a, c))
     i range(N-1) range N-1 N 1 a, b, c = iip() a iip() iip b c a -= 1 a 1 b -= 1 b 1 ret[a].append((b, c)) [a].append [a] ret a append (b, c) b c ret[b].append((a, c)) [b].append [b] ret b append (a, c) a c return ret ret N N def sort_tuples(l, index):  # タプルのリストを特定のインデックスでソートする
    if isinstance(l, list):
        l.sort(key=lambda x: x[index])
        return l
    else:
        l = list(l)
        return sorted(l, key=lambda x: x[index]) sort_tuples if isinstance(l, list):
        l.sort(key=lambda x: x[index])
        return l
    else:
        l = list(l)
        return sorted(l, key=lambda x: x[index]) isinstance(l, list) isinstance l list l.sort(key=lambda x: x[index]) l.sort l sort key=lambda x: x[index] key lambda x: x[index] x[index] x index x return l l l = list(l) l list(l) list l return sorted(l, key=lambda x: x[index]) sorted(l, key=lambda x: x[index]) sorted l key=lambda x: x[index] key lambda x: x[index] x[index] x index x l l index index def count_elements(l):  # リストの中身の個数を種類分けして辞書で返す
    d = {}
    for i in l:
        if i in d:
            d[i] += 1
        else:
            d[i] = 1
    return d count_elements d = {} d {} for i in l:
        if i in d:
            d[i] += 1
        else:
            d[i] = 1
     i l if i in d:
            d[i] += 1
        else:
            d[i] = 1
     i in d i d d[i] += 1 d[i] d i 1 d[i] = 1 d[i] d i 1 return d d l l def safeget(l, index, default="exception"):  # listの中身を取り出す時、listからはみ出たり
    if index >= len(l):                      # マイナスインデックスになったりするのを防ぐ
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]))
        else:
            return default
    elif index < 0:
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
    else:
        return l[index] safeget if index >= len(l):                      # マイナスインデックスになったりするのを防ぐ
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]))
        else:
            return default
    elif index < 0:
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
    else:
        return l[index] index >= len(l) index len(l) len l if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]))
        else:
            return default
     default == "exception" default "exception" raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"])) Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"])) Exception "".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]) "".join "" join ["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"] "safegetに不正な値 " index "が渡されました。配列の長さは" len(l) len l "です" return default default elif index < 0:
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
     index < 0 index 0 if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
     default == "exception" default "exception" raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"])) Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"])) Exception "".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]) "".join "" join ["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"] "safegetに不正な値 " index "が渡されました。負の値は許可されていません" return default default return l[index] l[index] l index l l index index default="exception" default "exception" def sortstr(s):  # 文字列をソートする
    return "".join(sorted(s)) sortstr return "".join(sorted(s)) "".join(sorted(s)) "".join "" join sorted(s) sorted s s s def iip_ord(startcode="a"):  # 文字列を数字の列に変換する(数字と文字は1:1対応)
    if isinstance(startcode, str):
        startcode = ord(startcode)
    return [ord(i) - startcode for i in input()] iip_ord if isinstance(startcode, str):
        startcode = ord(startcode)
     isinstance(startcode, str) isinstance startcode str startcode = ord(startcode) startcode ord(startcode) ord startcode ord(i) - startcode for i in input() for i in input() i input() input for i in input() ord(i) - startcode ord(i) ord i startcode return [ord(i) - startcode for i in input()] [ord(i) - startcode for i in input()] startcode="a" startcode "a" def YesNo(s):  # TrueFalseや1, 0をYesNoに変換する
    if s:
        print("Yes")
    else:
        print("No") YesNo if s:
        print("Yes")
    else:
        print("No") s print("Yes") print "Yes" print("No") print "No" s s def fprint(s):  # リストを平たくしてprintする(二次元リストを見やすくしたりとか)
    for i in s:
        print(i) fprint for i in s:
        print(i) i s print(i) print i s s def bitall(N):  # ビット全探索用のインデックスを出力
    ret = []
    for i in range(2 ** N):
        a = []
        for j in range(N):
            a.append(i % 2)
            i //= 2
        ret.append(a)
    return ret bitall ret = [] ret [] for i in range(2 ** N):
        a = []
        for j in range(N):
            a.append(i % 2)
            i //= 2
        ret.append(a)
     i range(2 ** N) range 2 ** N 2 N a = [] a [] for j in range(N):
            a.append(i % 2)
            i //= 2
         j range(N) range N a.append(i % 2) a.append a append i % 2 i 2 i //= 2 i 2 ret.append(a) ret.append ret append a return ret ret N N def split_print_space(s):  # リストの中身をスペース区切りで出力する
    print(" ".join([str(i) for i in s])) split_print_space str(i) for i in s for i in s i s for i in s str(i) str i print(" ".join([str(i) for i in s])) print " ".join([str(i) for i in s]) " ".join " " join [str(i) for i in s] s s def split_print_enter(s):  # リストの中身を改行区切りで出力する
    print("\n".join([str(i) for i in s])) split_print_enter str(i) for i in s for i in s i s for i in s str(i) str i print("\n".join([str(i) for i in s])) print "\n".join([str(i) for i in s]) "\n".join "\n" join [str(i) for i in s] s s def soinsuu_bunkai(n):  # 素因数分解
    ret = []
    for i in range(2, int(n ** 0.5) + 1):
        while n % i == 0:
            n //= i
            ret.append(i)
        if i > n:
            break
    if n != 1:
        ret.append(n)
    return ret soinsuu_bunkai ret = [] ret [] for i in range(2, int(n ** 0.5) + 1):
        while n % i == 0:
            n //= i
            ret.append(i)
        if i > n:
            break
     i range(2, int(n ** 0.5) + 1) range 2 int(n ** 0.5) + 1 int(n ** 0.5) int n ** 0.5 n 0.5 1 while n % i == 0:
            n //= i
            ret.append(i)
         n % i == 0 n % i n i 0 n //= i n i ret.append(i) ret.append ret append i if i > n:
            break
     i > n i n break if n != 1:
        ret.append(n)
     n != 1 n 1 ret.append(n) ret.append ret append n return ret ret n n def conbination(n, r, mod, test=False):  # nCrをmodを使って計算する
    if n <= 0:
        return 0
    if r == 0:
        return 1
    if r < 0:
        return 0
    if r == 1:
        return n
    ret = 1
    for i in range(n - r + 1, n + 1):
        ret *= i
        ret = ret % mod

    bunbo = 1
    for i in range(1, r + 1):
        bunbo *= i
        bunbo = bunbo % mod

    ret = (ret * inv(bunbo, mod)) % mod
    if test:
        # print(f"{n}C{r} = {ret}")
        pass
    return ret conbination if n <= 0:
        return 0
     n <= 0 n 0 return 0 0 if r == 0:
        return 1
     r == 0 r 0 return 1 1 if r < 0:
        return 0
     r < 0 r 0 return 0 0 if r == 1:
        return n
     r == 1 r 1 return n n ret = 1 ret 1 for i in range(n - r + 1, n + 1):
        ret *= i
        ret = ret % mod

     i range(n - r + 1, n + 1) range n - r + 1 n - r n r 1 n + 1 n 1 ret *= i ret i ret = ret % mod ret ret % mod ret mod bunbo = 1 bunbo 1 for i in range(1, r + 1):
        bunbo *= i
        bunbo = bunbo % mod

     i range(1, r + 1) range 1 r + 1 r 1 bunbo *= i bunbo i bunbo = bunbo % mod bunbo bunbo % mod bunbo mod ret = (ret * inv(bunbo, mod)) % mod ret (ret * inv(bunbo, mod)) % mod ret * inv(bunbo, mod) ret inv(bunbo, mod) inv bunbo mod mod if test:
        # print(f"{n}C{r} = {ret}")
        pass
     test return ret ret n n r r mod mod test=False test False def inv(n, mod):  #  modnにおける逆元を計算
    return power(n, mod - 2) inv return power(n, mod - 2) power(n, mod - 2) power n mod - 2 mod 2 n n mod mod def power(n, p, mod_=mod):  # 繰り返し二乗法でn**p % modを計算
    if p == 0:
        return 1
    if p % 2 == 0:
        return (power(n, p // 2, mod_) ** 2) % mod_
    if p % 2 == 1:
        return (n * power(n, p - 1, mod_)) % mod_ power if p == 0:
        return 1
     p == 0 p 0 return 1 1 if p % 2 == 0:
        return (power(n, p // 2, mod_) ** 2) % mod_
     p % 2 == 0 p % 2 p 2 0 return (power(n, p // 2, mod_) ** 2) % mod_ (power(n, p // 2, mod_) ** 2) % mod_ power(n, p // 2, mod_) ** 2 power(n, p // 2, mod_) power n p // 2 p 2 mod_ 2 mod_ if p % 2 == 1:
        return (n * power(n, p - 1, mod_)) % mod_ p % 2 == 1 p % 2 p 2 1 return (n * power(n, p - 1, mod_)) % mod_ (n * power(n, p - 1, mod_)) % mod_ n * power(n, p - 1, mod_) n power(n, p - 1, mod_) power n p - 1 p 1 mod_ mod_ n n p p mod_=mod mod_ mod def nibutan_func(func, target, left, right, side="left"): # 関数を二分探索
    l = left
    r = right
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if func(x) == target:
            return x
        elif func(x) > target:
            r = x
        else:
            l = x

    if side == "left" or func(x) == target:
        return l
    else:
        return r nibutan_func l = left l left r = right r right x = (l + r) // 2 x (l + r) // 2 l + r l r 2 while r-l > 1:
        x = (l+r)//2
        if func(x) == target:
            return x
        elif func(x) > target:
            r = x
        else:
            l = x

     r-l > 1 r-l r l 1 x = (l+r)//2 x (l+r)//2 l+r l r 2 if func(x) == target:
            return x
        elif func(x) > target:
            r = x
        else:
            l = x

     func(x) == target func(x) func x target return x x elif func(x) > target:
            r = x
         func(x) > target func(x) func x target r = x r x l = x l x if side == "left" or func(x) == target:
        return l
    else:
        return r side == "left" or func(x) == target side == "left" side "left" func(x) == target func(x) func x target return l l return r r func func target target left left right right side="left" side "left" def nibutan_list(list_, target, side="left"):  # リストを二分探索
    if not isinstance(list_, list):
        list_ = list(list_)

    l = 0
    r = len(list_)
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if list_[x] == target:
            return x
        elif list_[x] > target:
            r = x
        else:
            l = x

    if side == "left" or list_[x] == target:
        return l
    else:
        return r nibutan_list if not isinstance(list_, list):
        list_ = list(list_)

     not isinstance(list_, list) isinstance(list_, list) isinstance list_ list list_ = list(list_) list_ list(list_) list list_ l = 0 l 0 r = len(list_) r len(list_) len list_ x = (l + r) // 2 x (l + r) // 2 l + r l r 2 while r-l > 1:
        x = (l+r)//2
        if list_[x] == target:
            return x
        elif list_[x] > target:
            r = x
        else:
            l = x

     r-l > 1 r-l r l 1 x = (l+r)//2 x (l+r)//2 l+r l r 2 if list_[x] == target:
            return x
        elif list_[x] > target:
            r = x
        else:
            l = x

     list_[x] == target list_[x] list_ x target return x x elif list_[x] > target:
            r = x
         list_[x] > target list_[x] list_ x target r = x r x l = x l x if side == "left" or list_[x] == target:
        return l
    else:
        return r side == "left" or list_[x] == target side == "left" side "left" list_[x] == target list_[x] list_ x target return l l return r r list_ list_ target target side="left" side "left" class UfTree():
    def __init__(self, maxnum):
        self.parent = list(range(maxnum))
        self._size = [1] * maxnum
        self.rank = [0] * maxnum

    def size(self, a):
        return self._size[self.root(a)]

    def root(self, a):
        rank = 0
        cur = a
        while True:
            if self.parent[cur] == cur:
                #for i in path: # 経路圧縮
                #    self.parent[i] = cur
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

    def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb:
            return self

        self._size[ra] += self._size[rb]
        self.parent[rb] = ra
        return self UfTree def __init__(self, maxnum):
        self.parent = list(range(maxnum))
        self._size = [1] * maxnum
        self.rank = [0] * maxnum

     __init__ self.parent = list(range(maxnum)) self.parent self parent list(range(maxnum)) list range(maxnum) range maxnum self._size = [1] * maxnum self._size self _size [1] * maxnum [1] 1 maxnum self.rank = [0] * maxnum self.rank self rank [0] * maxnum [0] 0 maxnum self self maxnum maxnum def size(self, a):
        return self._size[self.root(a)]

     size return self._size[self.root(a)] self._size[self.root(a)] self._size self _size self.root(a) self.root self root a self self a a def root(self, a):
        rank = 0
        cur = a
        while True:
            if self.parent[cur] == cur:
                #for i in path: # 経路圧縮
                #    self.parent[i] = cur
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

     root rank = 0 rank 0 cur = a cur a while True:
            if self.parent[cur] == cur:
                #for i in path: # 経路圧縮
                #    self.parent[i] = cur
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

     True if self.parent[cur] == cur:
                #for i in path: # 経路圧縮
                #    self.parent[i] = cur
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

     self.parent[cur] == cur self.parent[cur] self.parent self parent cur cur return cur cur self.parent[cur] = self.parent[self.parent[cur]] self.parent[cur] self.parent self parent cur self.parent[self.parent[cur]] self.parent self parent self.parent[cur] self.parent self parent cur cur = self.parent[cur] cur self.parent[cur] self.parent self parent cur rank += 1 rank 1 self self a a def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb:
            return self

        self._size[ra] += self._size[rb]
        self.parent[rb] = ra
        return self unite ra = self.root(a) ra self.root(a) self.root self root a rb = self.root(b) rb self.root(b) self.root self root b if ra == rb:
            return self

         ra == rb ra rb return self self self._size[ra] += self._size[rb] self._size[ra] self._size self _size ra self._size[rb] self._size self _size rb self.parent[rb] = ra self.parent[rb] self.parent self parent rb ra return self self self self a a b b if __name__ == "__main__":
    main() __name__ == "__main__" __name__ "__main__" main() main def conbination(n, r, mod, test=False):  # nCrをmodを使って計算する
    if n <= 0:
        return 0
    if r == 0:
        return 1
    if r < 0:
        return 0
    if r == 1:
        return n
    ret = 1
    for i in range(n - r + 1, n + 1):
        ret *= i
        ret = ret % mod

    bunbo = 1
    for i in range(1, r + 1):
        bunbo *= i
        bunbo = bunbo % mod

    ret = (ret * inv(bunbo, mod)) % mod
    if test:
        # print(f"{n}C{r} = {ret}")
        pass
    return ret def conbination(n, r, mod, test=False):  # nCrをmodを使って計算する
    if n <= 0:
        return 0
    if r == 0:
        return 1
    if r < 0:
        return 0
    if r == 1:
        return n
    ret = 1
    for i in range(n - r + 1, n + 1):
        ret *= i
        ret = ret % mod

    bunbo = 1
    for i in range(1, r + 1):
        bunbo *= i
        bunbo = bunbo % mod

    ret = (ret * inv(bunbo, mod)) % mod
    if test:
        # print(f"{n}C{r} = {ret}")
        pass
    return ret conbination _NUMINT_ALL = list(range(10)) list(range(10)) _NUMINT_ALL def solve():
    N, M = iip(False)

    AB = iipt(M)
    AB.reverse()
    uf = UfTree(N)

    benlist = [0]

    cur = 0
    for a, b in AB:
        a -= 1
        b -= 1
        c1 = uf.size(a)
        c2 = uf.size(b)
        uf.unite(a, b)
        if c2 != uf.size(a):
            cur += c1*c2
        benlist.append(cur)

    t = benlist.pop()
    benlist.reverse()
    #print(benlist)

    ans = [t - i for i in benlist]

    split_print_enter(ans)


#####################################################ライブラリ集ここから def solve():
    N, M = iip(False)

    AB = iipt(M)
    AB.reverse()
    uf = UfTree(N)

    benlist = [0]

    cur = 0
    for a, b in AB:
        a -= 1
        b -= 1
        c1 = uf.size(a)
        c2 = uf.size(b)
        uf.unite(a, b)
        if c2 != uf.size(a):
            cur += c1*c2
        benlist.append(cur)

    t = benlist.pop()
    benlist.reverse()
    #print(benlist)

    ans = [t - i for i in benlist]

    split_print_enter(ans)


#####################################################ライブラリ集ここから solve def split_print_space(s):  # リストの中身をスペース区切りで出力する
    print(" ".join([str(i) for i in s])) def split_print_space(s):  # リストの中身をスペース区切りで出力する
    print(" ".join([str(i) for i in s])) split_print_space def iip_ord(startcode="a"):  # 文字列を数字の列に変換する(数字と文字は1:1対応)
    if isinstance(startcode, str):
        startcode = ord(startcode)
    return [ord(i) - startcode for i in input()] def iip_ord(startcode="a"):  # 文字列を数字の列に変換する(数字と文字は1:1対応)
    if isinstance(startcode, str):
        startcode = ord(startcode)
    return [ord(i) - startcode for i in input()] iip_ord def iip(listed=True):  # 数字のinputをlistで受け取る
    d = input().rstrip("\n").split()
    try:
        ret = [int(i) for i in d]
    except:
        ret = [int(i) if i in _NUMINT_ALL else i for i in d]
        if len(ret) == 1:
            return ret[0]

    if len(ret) == 1 and not listed:
        return ret[0]
    return ret def iip(listed=True):  # 数字のinputをlistで受け取る
    d = input().rstrip("\n").split()
    try:
        ret = [int(i) for i in d]
    except:
        ret = [int(i) if i in _NUMINT_ALL else i for i in d]
        if len(ret) == 1:
            return ret[0]

    if len(ret) == 1 and not listed:
        return ret[0]
    return ret iip def bitall(N):  # ビット全探索用のインデックスを出力
    ret = []
    for i in range(2 ** N):
        a = []
        for j in range(N):
            a.append(i % 2)
            i //= 2
        ret.append(a)
    return ret def bitall(N):  # ビット全探索用のインデックスを出力
    ret = []
    for i in range(2 ** N):
        a = []
        for j in range(N):
            a.append(i % 2)
            i //= 2
        ret.append(a)
    return ret bitall def safeget(l, index, default="exception"):  # listの中身を取り出す時、listからはみ出たり
    if index >= len(l):                      # マイナスインデックスになったりするのを防ぐ
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]))
        else:
            return default
    elif index < 0:
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
    else:
        return l[index] def safeget(l, index, default="exception"):  # listの中身を取り出す時、listからはみ出たり
    if index >= len(l):                      # マイナスインデックスになったりするのを防ぐ
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]))
        else:
            return default
    elif index < 0:
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
    else:
        return l[index] safeget def sort_tuples(l, index):  # タプルのリストを特定のインデックスでソートする
    if isinstance(l, list):
        l.sort(key=lambda x: x[index])
        return l
    else:
        l = list(l)
        return sorted(l, key=lambda x: x[index]) def sort_tuples(l, index):  # タプルのリストを特定のインデックスでソートする
    if isinstance(l, list):
        l.sort(key=lambda x: x[index])
        return l
    else:
        l = list(l)
        return sorted(l, key=lambda x: x[index]) sort_tuples def saidai_kouyakusuu(A):  # 最大公約数
    l = len(A)
    while True:
        m = min(A)
        mx = max(A)
        if m == mx:
            return m

        for i in range(l):
            if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m def saidai_kouyakusuu(A):  # 最大公約数
    l = len(A)
    while True:
        m = min(A)
        mx = max(A)
        if m == mx:
            return m

        for i in range(l):
            if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m saidai_kouyakusuu input = sys.stdin.readline sys.stdin.readline input def kiriage_warizan(a, b):
    return -(-a//b) def kiriage_warizan(a, b):
    return -(-a//b) kiriage_warizan mod2 = 2 ** 61 + 1 2 ** 61 + 1 mod2 def main():
    ans = solve()

    if ans is True or ans is False:
        YesNo(ans)
    elif ans is not None:
        print(ans) def main():
    ans = solve()

    if ans is True or ans is False:
        YesNo(ans)
    elif ans is not None:
        print(ans) main def power(n, p, mod_=mod):  # 繰り返し二乗法でn**p % modを計算
    if p == 0:
        return 1
    if p % 2 == 0:
        return (power(n, p // 2, mod_) ** 2) % mod_
    if p % 2 == 1:
        return (n * power(n, p - 1, mod_)) % mod_ def power(n, p, mod_=mod):  # 繰り返し二乗法でn**p % modを計算
    if p == 0:
        return 1
    if p % 2 == 0:
        return (power(n, p // 2, mod_) ** 2) % mod_
    if p % 2 == 1:
        return (n * power(n, p - 1, mod_)) % mod_ power def sortstr(s):  # 文字列をソートする
    return "".join(sorted(s)) def sortstr(s):  # 文字列をソートする
    return "".join(sorted(s)) sortstr def YesNo(s):  # TrueFalseや1, 0をYesNoに変換する
    if s:
        print("Yes")
    else:
        print("No") def YesNo(s):  # TrueFalseや1, 0をYesNoに変換する
    if s:
        print("Yes")
    else:
        print("No") YesNo mod = 10 ** 9 + 7 10 ** 9 + 7 mod def soinsuu_bunkai(n):  # 素因数分解
    ret = []
    for i in range(2, int(n ** 0.5) + 1):
        while n % i == 0:
            n //= i
            ret.append(i)
        if i > n:
            break
    if n != 1:
        ret.append(n)
    return ret def soinsuu_bunkai(n):  # 素因数分解
    ret = []
    for i in range(2, int(n ** 0.5) + 1):
        while n % i == 0:
            n //= i
            ret.append(i)
        if i > n:
            break
    if n != 1:
        ret.append(n)
    return ret soinsuu_bunkai def nibutan_list(list_, target, side="left"):  # リストを二分探索
    if not isinstance(list_, list):
        list_ = list(list_)

    l = 0
    r = len(list_)
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if list_[x] == target:
            return x
        elif list_[x] > target:
            r = x
        else:
            l = x

    if side == "left" or list_[x] == target:
        return l
    else:
        return r def nibutan_list(list_, target, side="left"):  # リストを二分探索
    if not isinstance(list_, list):
        list_ = list(list_)

    l = 0
    r = len(list_)
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if list_[x] == target:
            return x
        elif list_[x] > target:
            r = x
        else:
            l = x

    if side == "left" or list_[x] == target:
        return l
    else:
        return r nibutan_list def fprint(s):  # リストを平たくしてprintする(二次元リストを見やすくしたりとか)
    for i in s:
        print(i) def fprint(s):  # リストを平たくしてprintする(二次元リストを見やすくしたりとか)
    for i in s:
        print(i) fprint def make_graph_edge_flat(N):  # グラフ作成のための辺をリストで返す
    ret = []
    for i in range(N-1):
        a, b, c = iip()
        a -= 1
        b -= 1
        ret[a].append((b, c))
        ret[b].append((a, c))
    return ret def make_graph_edge_flat(N):  # グラフ作成のための辺をリストで返す
    ret = []
    for i in range(N-1):
        a, b, c = iip()
        a -= 1
        b -= 1
        ret[a].append((b, c))
        ret[b].append((a, c))
    return ret make_graph_edge_flat def inv(n, mod):  #  modnにおける逆元を計算
    return power(n, mod - 2) def inv(n, mod):  #  modnにおける逆元を計算
    return power(n, mod - 2) inv def count_elements(l):  # リストの中身の個数を種類分けして辞書で返す
    d = {}
    for i in l:
        if i in d:
            d[i] += 1
        else:
            d[i] = 1
    return d def count_elements(l):  # リストの中身の個数を種類分けして辞書で返す
    d = {}
    for i in l:
        if i in d:
            d[i] += 1
        else:
            d[i] = 1
    return d count_elements def iipt(l, listed=False, num_only=True):  # 縦向きに並んでいるデータをリストに落とし込む(iip利用)
    ret = []
    for i in range(l):
        ret.append(iip(listed=listed))
    return ret def iipt(l, listed=False, num_only=True):  # 縦向きに並んでいるデータをリストに落とし込む(iip利用)
    ret = []
    for i in range(l):
        ret.append(iip(listed=listed))
    return ret iipt class UfTree():
    def __init__(self, maxnum):
        self.parent = list(range(maxnum))
        self._size = [1] * maxnum
        self.rank = [0] * maxnum

    def size(self, a):
        return self._size[self.root(a)]

    def root(self, a):
        rank = 0
        cur = a
        while True:
            if self.parent[cur] == cur:
                #for i in path: # 経路圧縮
                #    self.parent[i] = cur
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

    def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb:
            return self

        self._size[ra] += self._size[rb]
        self.parent[rb] = ra
        return self class UfTree():
    def __init__(self, maxnum):
        self.parent = list(range(maxnum))
        self._size = [1] * maxnum
        self.rank = [0] * maxnum

    def size(self, a):
        return self._size[self.root(a)]

    def root(self, a):
        rank = 0
        cur = a
        while True:
            if self.parent[cur] == cur:
                #for i in path: # 経路圧縮
                #    self.parent[i] = cur
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

    def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb:
            return self

        self._size[ra] += self._size[rb]
        self.parent[rb] = ra
        return self UfTree def split_print_enter(s):  # リストの中身を改行区切りで出力する
    print("\n".join([str(i) for i in s])) def split_print_enter(s):  # リストの中身を改行区切りで出力する
    print("\n".join([str(i) for i in s])) split_print_enter def nibutan_func(func, target, left, right, side="left"): # 関数を二分探索
    l = left
    r = right
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if func(x) == target:
            return x
        elif func(x) > target:
            r = x
        else:
            l = x

    if side == "left" or func(x) == target:
        return l
    else:
        return r def nibutan_func(func, target, left, right, side="left"): # 関数を二分探索
    l = left
    r = right
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if func(x) == target:
            return x
        elif func(x) > target:
            r = x
        else:
            l = x

    if side == "left" or func(x) == target:
        return l
    else:
        return r nibutan_func
mod = 10 ** 9 + 7
mod2 = 2 ** 61 + 1
from collections import deque
import heapq
import time
from bisect import bisect_left, insort_left, bisect_right
import sys

input = sys.stdin.readline
_NUMINT_ALL = list(range(10))


def main():
    ans = solve()

    if ans is True or ans is False:
        YesNo(ans)
    elif ans is not None:
        print(ans)


def solve():
    N, M = iip(False)

    AB = iipt(M)
    AB.reverse()
    uf = UfTree(N)

    benlist = [0]

    cur = 0
    for a, b in AB:
        a -= 1
        b -= 1
        c1 = uf.size(a)
        c2 = uf.size(b)
        uf.unite(a, b)
        if c2 != uf.size(a):
            cur += c1*c2
        benlist.append(cur)

    t = benlist.pop()
    benlist.reverse()
    #print(benlist)

    ans = [t - i for i in benlist]

    split_print_enter(ans)


#####################################################ライブラリ集ここから

def kiriage_warizan(a, b):
    return -(-a//b)


def iip(listed=True):  # 数字のinputをlistで受け取る
    d = input().rstrip("\n").split()
    try:
        ret = [int(i) for i in d]
    except:
        ret = [int(i) if i in _NUMINT_ALL else i for i in d]
        if len(ret) == 1:
            return ret[0]

    if len(ret) == 1 and not listed:
        return ret[0]
    return ret

def iipt(l, listed=False, num_only=True):  # 縦向きに並んでいるデータをリストに落とし込む(iip利用)
    ret = []
    for i in range(l):
        ret.append(iip(listed=listed))
    return ret


def saidai_kouyakusuu(A):  # 最大公約数
    l = len(A)
    while True:
        m = min(A)
        mx = max(A)
        if m == mx:
            return m

        for i in range(l):
            if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m


def make_graph_edge_flat(N):  # グラフ作成のための辺をリストで返す
    ret = []
    for i in range(N-1):
        a, b, c = iip()
        a -= 1
        b -= 1
        ret[a].append((b, c))
        ret[b].append((a, c))
    return ret


def sort_tuples(l, index):  # タプルのリストを特定のインデックスでソートする
    if isinstance(l, list):
        l.sort(key=lambda x: x[index])
        return l
    else:
        l = list(l)
        return sorted(l, key=lambda x: x[index])


def count_elements(l):  # リストの中身の個数を種類分けして辞書で返す
    d = {}
    for i in l:
        if i in d:
            d[i] += 1
        else:
            d[i] = 1
    return d


def safeget(l, index, default="exception"):  # listの中身を取り出す時、listからはみ出たり
    if index >= len(l):                      # マイナスインデックスになったりするのを防ぐ
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]))
        else:
            return default
    elif index < 0:
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
    else:
        return l[index]


def sortstr(s):  # 文字列をソートする
    return "".join(sorted(s))


def iip_ord(startcode="a"):  # 文字列を数字の列に変換する(数字と文字は1:1対応)
    if isinstance(startcode, str):
        startcode = ord(startcode)
    return [ord(i) - startcode for i in input()]


def YesNo(s):  # TrueFalseや1, 0をYesNoに変換する
    if s:
        print("Yes")
    else:
        print("No")


def fprint(s):  # リストを平たくしてprintする(二次元リストを見やすくしたりとか)
    for i in s:
        print(i)


def bitall(N):  # ビット全探索用のインデックスを出力
    ret = []
    for i in range(2 ** N):
        a = []
        for j in range(N):
            a.append(i % 2)
            i //= 2
        ret.append(a)
    return ret

def split_print_space(s):  # リストの中身をスペース区切りで出力する
    print(" ".join([str(i) for i in s]))


def split_print_enter(s):  # リストの中身を改行区切りで出力する
    print("\n".join([str(i) for i in s]))


def soinsuu_bunkai(n):  # 素因数分解
    ret = []
    for i in range(2, int(n ** 0.5) + 1):
        while n % i == 0:
            n //= i
            ret.append(i)
        if i > n:
            break
    if n != 1:
        ret.append(n)
    return ret


def conbination(n, r, mod, test=False):  # nCrをmodを使って計算する
    if n <= 0:
        return 0
    if r == 0:
        return 1
    if r < 0:
        return 0
    if r == 1:
        return n
    ret = 1
    for i in range(n - r + 1, n + 1):
        ret *= i
        ret = ret % mod

    bunbo = 1
    for i in range(1, r + 1):
        bunbo *= i
        bunbo = bunbo % mod

    ret = (ret * inv(bunbo, mod)) % mod
    if test:
        # print(f"{n}C{r} = {ret}")
        pass
    return ret


def inv(n, mod):  #  modnにおける逆元を計算
    return power(n, mod - 2)


def power(n, p, mod_=mod):  # 繰り返し二乗法でn**p % modを計算
    if p == 0:
        return 1
    if p % 2 == 0:
        return (power(n, p // 2, mod_) ** 2) % mod_
    if p % 2 == 1:
        return (n * power(n, p - 1, mod_)) % mod_


def nibutan_func(func, target, left, right, side="left"): # 関数を二分探索
    l = left
    r = right
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if func(x) == target:
            return x
        elif func(x) > target:
            r = x
        else:
            l = x

    if side == "left" or func(x) == target:
        return l
    else:
        return r


def nibutan_list(list_, target, side="left"):  # リストを二分探索
    if not isinstance(list_, list):
        list_ = list(list_)

    l = 0
    r = len(list_)
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if list_[x] == target:
            return x
        elif list_[x] > target:
            r = x
        else:
            l = x

    if side == "left" or list_[x] == target:
        return l
    else:
        return r


class UfTree():
    def __init__(self, maxnum):
        self.parent = list(range(maxnum))
        self._size = [1] * maxnum
        self.rank = [0] * maxnum

    def size(self, a):
        return self._size[self.root(a)]

    def root(self, a):
        rank = 0
        cur = a
        while True:
            if self.parent[cur] == cur:
                #for i in path: # 経路圧縮
                #    self.parent[i] = cur
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

    def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb:
            return self

        self._size[ra] += self._size[rb]
        self.parent[rb] = ra
        return self

if __name__ == "__main__":
    main()
