Buggy python submission (verdict: Time Limit Exceeded):
import numpy as np
N,M = map(int,input().split())

bridges = [list(map(int,input().split())) for i in range(M)]

roots = np.array((range(0,N)))
a =int(N*(N-1)/2)
ans = [a]

for i in range(0,M)[::-1]:
    island0, island1 = bridges[i][0],bridges[i][1]

    if roots[island0-1] == roots[island1-1]:
        ans.append(int(a))
        continue
        
    num_island0 = np.sum(roots==roots[island0-1])
    num_island1 = np.sum(roots==roots[island1-1])
    num_island01 = num_island0 + num_island1



    # num_island0 = roots.count(roots[island0-1])
    # num_island1 = roots.count(roots[island1-1])
    # num_island01 = num_island0 + num_island1
    if roots[island1-1] != island1: # merge
        min_i = min(roots[island0-1],roots[island1-1])
        max_i = max(roots[island0-1],roots[island1-1])
        roots = np.where(roots==max_i,min_i,roots)

    else: # つなげる
        roots[island1-1] = roots[island0-1]
    
    a -= (num_island01*(num_island01-1) - num_island0*(num_island0-1) - num_island1 *(num_island1-1))/2
    ans.append(int(a))

[print(ans[i]) for i in range(M)[::-1]]


Fixed submission:

class UnionFindTree():
    # Union find tree
    # 2つの効率化　経路圧縮、ランク
    # つなげることはできるか分離することはできないので、木をつなげる方向に利用する
    # 
    def __init__(self, node_size):
        # node_num: 全体のノード数
        # parent: ノードがrootなら-1、親がいれば親の番号を入れる
        # size:
        # rank:  
        self.parent =[-1] * node_size 
        self.size = [1] * node_size
        self.rank = [1] * node_size
    
    def find_root(self,node):
        # node属する木のrootを探す
        # たどった経路に含まれるnodeの親をrootにつなぎ替える
        if self.parent[node] == -1:             # 自身がrootの場合
            root = node
        else:                                   # 自身がrootでない場合
            root = self.find_root(self.parent[node]) # 再帰的にrootを探す
            self.parent[node] = root            # たどった経路に含まれるnodeの親をrootにつなぎ替える(経路圧縮)
        return root

    def unite(self,node0, node1):
        # node0とnode1が含まれる木を結合する
        
        #node0 node1のrootを求める
        root0 = self.find_root(node0) 
        root1 = self.find_root(node1)

        if root0 != root1:
            # rankを比較しrankが小さい方の木を大きい方の木のrootにつなげる
            # rank is sameのときのみrankが増える
            rank0 = self.rank[root0]
            rank1 = self.rank[root1]

            if rank0 == rank1: # rank is same
                self.parent[root1] = root0
                self.size[root0] += self.size[root1]
                self.rank[root0] += 1
            elif rank0 > rank1:
                self.parent[root1] = root0
                self.size[root0] += self.size[root1]
            else:
                self.parent[root0] = root1
                self.size[root1] += self.size[root0]

            


N,M = map(int,input().split())
bridges = [list(map(int,input().split())) for i in range(M)]

UFT = UnionFindTree(N)

a = int(N*(N-1)/2) # 不便さ
ans = [a]

for i in range(1,M)[::-1]:
    island0_num, island1_num = bridges[i][0]-1, bridges[i][1]-1 
    root0 = UFT.find_root(island0_num)
    root1 = UFT.find_root(island1_num)
    if root0 != root1:
        size0 =  UFT.size[root0]
        size1 =  UFT.size[root1]
        UFT.unite(island0_num,island1_num)
        a -= size0 * size1
    ans.append(int(a))

[print(ans[i]) for i in range(M)[::-1]]

Buggy python submission (verdict: Runtime Error):
import numpy as np
N,M = map(int,input().split())

bridges = [list(map(int,input().split())) for i in range(M)]

roots = np.array((range(0,N)))
a =int(N*(N-1)/2)
ans = [a]

for i in range(0,M)[::-1]:
    island0, island1 = bridges[i][0],bridges[i][1]

    if roots[island0-1] == roots[island1-1]:
        ans.append(int(a))
        continue

    num_island0 = roots.count(roots[island0-1])
    num_island1 = roots.count(roots[island1-1])
    num_island01 = num_island0 + num_island1
    if roots[island1-1] != island1: # merge
        min_i = min(roots[island0-1],roots[island1-1])
        max_i = max(roots[island0-1],roots[island1-1])
        roots = [min_i if root==max_i else root for root in roots]        
    else: # つなげる
        roots[island1-1] = roots[island0-1]
    
    a -= (num_island01*(num_island01-1) - num_island0*(num_island0-1) - num_island1 *(num_island1-1))/2
    ans.append(int(a))

[print(ans[i]) for i in range(M)[::-1]]


Fixed submission:

class UnionFindTree():
    # Union find tree
    # 2つの効率化　経路圧縮、ランク
    # つなげることはできるか分離することはできないので、木をつなげる方向に利用する
    # 
    def __init__(self, node_size):
        # node_num: 全体のノード数
        # parent: ノードがrootなら-1、親がいれば親の番号を入れる
        # size:
        # rank:  
        self.parent =[-1] * node_size 
        self.size = [1] * node_size
        self.rank = [1] * node_size
    
    def find_root(self,node):
        # node属する木のrootを探す
        # たどった経路に含まれるnodeの親をrootにつなぎ替える
        if self.parent[node] == -1:             # 自身がrootの場合
            root = node
        else:                                   # 自身がrootでない場合
            root = self.find_root(self.parent[node]) # 再帰的にrootを探す
            self.parent[node] = root            # たどった経路に含まれるnodeの親をrootにつなぎ替える(経路圧縮)
        return root

    def unite(self,node0, node1):
        # node0とnode1が含まれる木を結合する
        
        #node0 node1のrootを求める
        root0 = self.find_root(node0) 
        root1 = self.find_root(node1)

        if root0 != root1:
            # rankを比較しrankが小さい方の木を大きい方の木のrootにつなげる
            # rank is sameのときのみrankが増える
            rank0 = self.rank[root0]
            rank1 = self.rank[root1]

            if rank0 == rank1: # rank is same
                self.parent[root1] = root0
                self.size[root0] += self.size[root1]
                self.rank[root0] += 1
            elif rank0 > rank1:
                self.parent[root1] = root0
                self.size[root0] += self.size[root1]
            else:
                self.parent[root0] = root1
                self.size[root1] += self.size[root0]

            


N,M = map(int,input().split())
bridges = [list(map(int,input().split())) for i in range(M)]

UFT = UnionFindTree(N)

a = int(N*(N-1)/2) # 不便さ
ans = [a]

for i in range(1,M)[::-1]:
    island0_num, island1_num = bridges[i][0]-1, bridges[i][1]-1 
    root0 = UFT.find_root(island0_num)
    root1 = UFT.find_root(island1_num)
    if root0 != root1:
        size0 =  UFT.size[root0]
        size1 =  UFT.size[root1]
        UFT.unite(island0_num,island1_num)
        a -= size0 * size1
    ans.append(int(a))

[print(ans[i]) for i in range(M)[::-1]]

Buggy python submission (verdict: Time Limit Exceeded):
import collections
N,M = map(int,input().split())

bridges = [list(map(int,input().split())) for i in range(M)]

roots = list(range(0,N))
a =int(N*(N-1)/2)
ans = [a]

for i in range(0,M)[::-1]:
    island0, island1 = bridges[i][0],bridges[i][1]

    if roots[island0-1] == roots[island1-1]:
        ans.append(int(a))
        continue

    num_island0 = roots.count(roots[island0-1])
    num_island1 = roots.count(roots[island1-1])
    num_island01 = num_island0 + num_island1
    if roots[island1-1] != island1: # merge
        min_i = min(roots[island0-1],roots[island1-1])
        max_i = max(roots[island0-1],roots[island1-1])
        roots = [min_i if root==max_i else root for root in roots]        
    else: # つなげる
        roots[island1-1] = roots[island0-1]
    
    a -= (num_island01*(num_island01-1) - num_island0*(num_island0-1) - num_island1 *(num_island1-1))/2
    ans.append(int(a))

[print(ans[i]) for i in range(M)[::-1]]


Fixed submission:

class UnionFindTree():
    # Union find tree
    # 2つの効率化　経路圧縮、ランク
    # つなげることはできるか分離することはできないので、木をつなげる方向に利用する
    # 
    def __init__(self, node_size):
        # node_num: 全体のノード数
        # parent: ノードがrootなら-1、親がいれば親の番号を入れる
        # size:
        # rank:  
        self.parent =[-1] * node_size 
        self.size = [1] * node_size
        self.rank = [1] * node_size
    
    def find_root(self,node):
        # node属する木のrootを探す
        # たどった経路に含まれるnodeの親をrootにつなぎ替える
        if self.parent[node] == -1:             # 自身がrootの場合
            root = node
        else:                                   # 自身がrootでない場合
            root = self.find_root(self.parent[node]) # 再帰的にrootを探す
            self.parent[node] = root            # たどった経路に含まれるnodeの親をrootにつなぎ替える(経路圧縮)
        return root

    def unite(self,node0, node1):
        # node0とnode1が含まれる木を結合する
        
        #node0 node1のrootを求める
        root0 = self.find_root(node0) 
        root1 = self.find_root(node1)

        if root0 != root1:
            # rankを比較しrankが小さい方の木を大きい方の木のrootにつなげる
            # rank is sameのときのみrankが増える
            rank0 = self.rank[root0]
            rank1 = self.rank[root1]

            if rank0 == rank1: # rank is same
                self.parent[root1] = root0
                self.size[root0] += self.size[root1]
                self.rank[root0] += 1
            elif rank0 > rank1:
                self.parent[root1] = root0
                self.size[root0] += self.size[root1]
            else:
                self.parent[root0] = root1
                self.size[root1] += self.size[root0]

            


N,M = map(int,input().split())
bridges = [list(map(int,input().split())) for i in range(M)]

UFT = UnionFindTree(N)

a = int(N*(N-1)/2) # 不便さ
ans = [a]

for i in range(1,M)[::-1]:
    island0_num, island1_num = bridges[i][0]-1, bridges[i][1]-1 
    root0 = UFT.find_root(island0_num)
    root1 = UFT.find_root(island1_num)
    if root0 != root1:
        size0 =  UFT.size[root0]
        size1 =  UFT.size[root1]
        UFT.unite(island0_num,island1_num)
        a -= size0 * size1
    ans.append(int(a))

[print(ans[i]) for i in range(M)[::-1]]

Buggy python submission (verdict: Time Limit Exceeded):
import collections
N,M = map(int,input().split())

bridges = [list(map(int,input().split())) for i in range(M)]

roots = list(range(0,N))
a =int(N*(N-1)/2)
ans = [a]

for i in range(0,M)[::-1]:
    a =int(N*(N-1)/2)
    island0, island1 = bridges[i][0],bridges[i][1]
    if roots[island1-1] != island1: # merge
        min_i = min(roots[island0-1],roots[island1-1])
        max_i = max(roots[island0-1],roots[island1-1])
        roots = [min_i if root==max_i else root for root in roots]        
    else: # つなげる
        roots[island1-1] = roots[island0-1]
    
    unique_root = list(set(roots))
    for root in unique_root:
        b = roots.count(root)
        if b >=2:
            a -= b*(b-1)/2
    ans.append(int(a))

[print(ans[i]) for i in range(M)[::-1]]


Fixed submission:

class UnionFindTree():
    # Union find tree
    # 2つの効率化　経路圧縮、ランク
    # つなげることはできるか分離することはできないので、木をつなげる方向に利用する
    # 
    def __init__(self, node_size):
        # node_num: 全体のノード数
        # parent: ノードがrootなら-1、親がいれば親の番号を入れる
        # size:
        # rank:  
        self.parent =[-1] * node_size 
        self.size = [1] * node_size
        self.rank = [1] * node_size
    
    def find_root(self,node):
        # node属する木のrootを探す
        # たどった経路に含まれるnodeの親をrootにつなぎ替える
        if self.parent[node] == -1:             # 自身がrootの場合
            root = node
        else:                                   # 自身がrootでない場合
            root = self.find_root(self.parent[node]) # 再帰的にrootを探す
            self.parent[node] = root            # たどった経路に含まれるnodeの親をrootにつなぎ替える(経路圧縮)
        return root

    def unite(self,node0, node1):
        # node0とnode1が含まれる木を結合する
        
        #node0 node1のrootを求める
        root0 = self.find_root(node0) 
        root1 = self.find_root(node1)

        if root0 != root1:
            # rankを比較しrankが小さい方の木を大きい方の木のrootにつなげる
            # rank is sameのときのみrankが増える
            rank0 = self.rank[root0]
            rank1 = self.rank[root1]

            if rank0 == rank1: # rank is same
                self.parent[root1] = root0
                self.size[root0] += self.size[root1]
                self.rank[root0] += 1
            elif rank0 > rank1:
                self.parent[root1] = root0
                self.size[root0] += self.size[root1]
            else:
                self.parent[root0] = root1
                self.size[root1] += self.size[root0]

            


N,M = map(int,input().split())
bridges = [list(map(int,input().split())) for i in range(M)]

UFT = UnionFindTree(N)

a = int(N*(N-1)/2) # 不便さ
ans = [a]

for i in range(1,M)[::-1]:
    island0_num, island1_num = bridges[i][0]-1, bridges[i][1]-1 
    root0 = UFT.find_root(island0_num)
    root1 = UFT.find_root(island1_num)
    if root0 != root1:
        size0 =  UFT.size[root0]
        size1 =  UFT.size[root1]
        UFT.unite(island0_num,island1_num)
        a -= size0 * size1
    ans.append(int(a))

[print(ans[i]) for i in range(M)[::-1]]