Buggy python submission (verdict: Time Limit Exceeded):
class UnionFind():
    '''
    @properties
        parents:
            - 各要素の親要素の番号を格納するリスト
            - 要素が根の場合はそのグループの要素数を格納する
    '''
    def __init__(self,n):
        self.n = n 
        self.parents = [-1] * n

    def __str__(self):
        return '\n'.join('{}: {}'.format(r,self.members(r)) for r in self.roots())
    
    def find(self,x):
        if self.parents[x] < 0: #初期値の場合
            return x
        else:
            self.parents[x] = self.find(self.parents[x]) #どの根に紐づいているかを判断する
            return self.parents[x]

    def union(self,x,y):

        x = self.find(x) #どの根に紐づいているかを判断する
        y = self.find(y) #どの根に紐づいているかを判断する

        if x == y: #同じ根に紐づいている場合は何もしない
            return
        
        if self.parents[x] > self.parents[y]:
            x,y = y,x
        
        self.parents[x] += self.parents[y] #根の個数を増やす。。？
        self.parents[y] = x #根を変更する

    def members(self,x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i,x in enumerate(self.parents) if x < 0 ]
    
    def weighted_roots_sizes(self):
        return [ self.size(i) for i,x in enumerate(self.parents) if x < -1 ]
    
    def size(self,x):
        return -self.parents[self.find(x)]

N,M = map(int,input().split(' '))
bridges = [ list(map(int,input().split(' '))) for _ in range(M) ]
uf = UnionFind(N)
base_num = N * (N-1) //2
output_list = [0]*(M+1)
output_list[M] = base_num

for i in reversed(range(M)):
     bridge_from = bridges[i][0] - 1
     bridge_to = bridges[i][1] - 1
     uf.union(bridge_from,bridge_to)
     current_amount = 0
     for size in uf.weighted_roots_sizes():
         current_amount += size * (size -1) //2
     output_list[i] = base_num - current_amount

for i in range(1,M+1):
    print(output_list[i])


Fixed submission:
class UnionFind():
    '''
    @properties
        parents:
            - 各要素の親要素の番号を格納するリスト
            - 要素が根の場合はそのグループの要素数を格納する
    '''
    def __init__(self,n):
        self.n = n 
        self.parents = [-1] * n

    def __str__(self):
        return '\n'.join('{}: {}'.format(r,self.members(r)) for r in self.roots())
    
    def find(self,x):
        if self.parents[x] < 0: #初期値の場合
            return x
        else:
            self.parents[x] = self.find(self.parents[x]) #どの根に紐づいているかを判断する
            return self.parents[x]

    def union(self,x,y):

        x = self.find(x) #どの根に紐づいているかを判断する
        y = self.find(y) #どの根に紐づいているかを判断する

        if x == y: #同じ根に紐づいている場合は何もしない
            return
        
        if self.parents[x] > self.parents[y]:
            x,y = y,x
        
        self.parents[x] += self.parents[y] #根の個数を増やす。。？
        self.parents[y] = x #根を変更する

    def members(self,x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i,x in enumerate(self.parents) if x < 0 ]
    
    def weighted_roots_sizes(self):
        return [ self.size(i) for i,x in enumerate(self.parents) if x < -1 ]
    
    def size(self,x):
        return -self.parents[self.find(x)]

N,M = map(int,input().split(' '))
bridges = [ list(map(int,input().split(' '))) for _ in range(M) ]
uf = UnionFind(N)
base_num = N * (N-1) //2
output_list = [0]*(M+1)
output_list[M] = base_num

for i in reversed(range(M)):
    bridge_from = bridges[i][0] - 1
    bridge_to = bridges[i][1] - 1
    current_amount = 0
    if uf.find(bridge_from) == uf.find(bridge_to):
        output_list[i] = output_list[i+1]
        continue
    output_list[i] = output_list[i+1] - uf.size(bridge_from) * uf.size(bridge_to)
    uf.union(bridge_from,bridge_to)

for i in range(1,M+1):
    print(output_list[i])

Buggy python submission (verdict: Time Limit Exceeded):
N,M = map(int,input().split(' '))
bridges = [ list(map(int,input().split(' '))) for _ in range(M) ]

output_list = [0]*(M+1)
unreach_bridge_len = N +1
base_num = N * (N-1) //2
output_list[M] = base_num
cluster_list = []

dp = [ [] for _ in range(M)]
next_length = 0
current_length = 0
for i in reversed(range(1,M)):
    flag = True
    first_belongs = -1
    second_belongs = -1
    next_length = 0
    for s in  range(len(dp[i])): #enumerate(cluster_list)
        inner = True 
        if bridges[i][0] in dp[i][s]:
            first_belongs = s
            inner = False
        if bridges[i][1] in dp[i][s]:
            second_belongs = s
            inner = False
        if  (bridges[i][0] in dp[i][s] and bridges[i][1] in dp[i][s]) or inner:
            dp[i-1].append(dp[i][s])
            
    if first_belongs == -1 and second_belongs == -1:
        dp[i-1].append({bridges[i][0],bridges[i][1]})
    elif first_belongs == -1:
        dp[i-1].append(dp[i][second_belongs] | {bridges[i][0]})
        #dp[i-1][second_belongs].add()
        #cluster_list[second_belongs].add(bridges[i][0])
    elif second_belongs == -1:
        dp[i-1].append(dp[i][first_belongs] | {bridges[i][1]})
        #dp[i-1][first_belongs].add(bridges[i][1])
        #cluster_list[first_belongs].add(bridges[i][1])
    elif first_belongs != second_belongs:
        dp[i-1].append(dp[i][first_belongs] | dp[i][second_belongs])
    current_amount = 0
    for s in range(len(dp[i-1])):
        current_amount += len(dp[i-1][s]) * (len(dp[i-1][s]) -1) //2
    output_list[i] = base_num - current_amount
    current_length = next_length

for i in range(1,M+1):
    print(output_list[i])

Fixed submission:
class UnionFind():
    '''
    @properties
        parents:
            - 各要素の親要素の番号を格納するリスト
            - 要素が根の場合はそのグループの要素数を格納する
    '''
    def __init__(self,n):
        self.n = n 
        self.parents = [-1] * n

    def __str__(self):
        return '\n'.join('{}: {}'.format(r,self.members(r)) for r in self.roots())
    
    def find(self,x):
        if self.parents[x] < 0: #初期値の場合
            return x
        else:
            self.parents[x] = self.find(self.parents[x]) #どの根に紐づいているかを判断する
            return self.parents[x]

    def union(self,x,y):

        x = self.find(x) #どの根に紐づいているかを判断する
        y = self.find(y) #どの根に紐づいているかを判断する

        if x == y: #同じ根に紐づいている場合は何もしない
            return
        
        if self.parents[x] > self.parents[y]:
            x,y = y,x
        
        self.parents[x] += self.parents[y] #根の個数を増やす。。？
        self.parents[y] = x #根を変更する

    def members(self,x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i,x in enumerate(self.parents) if x < 0 ]
    
    def weighted_roots_sizes(self):
        return [ self.size(i) for i,x in enumerate(self.parents) if x < -1 ]
    
    def size(self,x):
        return -self.parents[self.find(x)]

N,M = map(int,input().split(' '))
bridges = [ list(map(int,input().split(' '))) for _ in range(M) ]
uf = UnionFind(N)
base_num = N * (N-1) //2
output_list = [0]*(M+1)
output_list[M] = base_num

for i in reversed(range(M)):
    bridge_from = bridges[i][0] - 1
    bridge_to = bridges[i][1] - 1
    current_amount = 0
    if uf.find(bridge_from) == uf.find(bridge_to):
        output_list[i] = output_list[i+1]
        continue
    output_list[i] = output_list[i+1] - uf.size(bridge_from) * uf.size(bridge_to)
    uf.union(bridge_from,bridge_to)

for i in range(1,M+1):
    print(output_list[i])

Buggy python submission (verdict: Time Limit Exceeded):
N,M = map(int,input().split(' '))
bridges = [ list(map(int,input().split(' '))) for _ in range(M) ]

output_list = [0]*(M+1)
unreach_bridge_len = N +1
base_num = N * (N-1) //2
output_list[M] = base_num
cluster_list = []

for i in reversed(range(M)):
    flag = True
    first_belongs = -1
    second_belongs = -1
    for idx,cluster in enumerate(cluster_list):
        if bridges[i][0] in cluster:
            first_belongs = idx
        if bridges[i][1] in cluster:
            second_belongs = idx
    if first_belongs == -1 and second_belongs == -1:
        cluster_list.append({bridges[i][0],bridges[i][1]})
    elif first_belongs == -1:
        cluster_list[second_belongs].add(bridges[i][0])
    elif second_belongs == -1:
        cluster_list[first_belongs].add(bridges[i][1])
    elif first_belongs != second_belongs:
        cluster_list[first_belongs] = cluster_list[first_belongs] | cluster_list[second_belongs]
        del cluster_list[second_belongs]
    current_amount = 0
    for cluster in cluster_list:
        current_amount += len(cluster) * (len(cluster) -1) //2
    output_list[i] = base_num - current_amount

for i in range(1,M+1):
    print(output_list[i])

Fixed submission:
class UnionFind():
    '''
    @properties
        parents:
            - 各要素の親要素の番号を格納するリスト
            - 要素が根の場合はそのグループの要素数を格納する
    '''
    def __init__(self,n):
        self.n = n 
        self.parents = [-1] * n

    def __str__(self):
        return '\n'.join('{}: {}'.format(r,self.members(r)) for r in self.roots())
    
    def find(self,x):
        if self.parents[x] < 0: #初期値の場合
            return x
        else:
            self.parents[x] = self.find(self.parents[x]) #どの根に紐づいているかを判断する
            return self.parents[x]

    def union(self,x,y):

        x = self.find(x) #どの根に紐づいているかを判断する
        y = self.find(y) #どの根に紐づいているかを判断する

        if x == y: #同じ根に紐づいている場合は何もしない
            return
        
        if self.parents[x] > self.parents[y]:
            x,y = y,x
        
        self.parents[x] += self.parents[y] #根の個数を増やす。。？
        self.parents[y] = x #根を変更する

    def members(self,x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i,x in enumerate(self.parents) if x < 0 ]
    
    def weighted_roots_sizes(self):
        return [ self.size(i) for i,x in enumerate(self.parents) if x < -1 ]
    
    def size(self,x):
        return -self.parents[self.find(x)]

N,M = map(int,input().split(' '))
bridges = [ list(map(int,input().split(' '))) for _ in range(M) ]
uf = UnionFind(N)
base_num = N * (N-1) //2
output_list = [0]*(M+1)
output_list[M] = base_num

for i in reversed(range(M)):
    bridge_from = bridges[i][0] - 1
    bridge_to = bridges[i][1] - 1
    current_amount = 0
    if uf.find(bridge_from) == uf.find(bridge_to):
        output_list[i] = output_list[i+1]
        continue
    output_list[i] = output_list[i+1] - uf.size(bridge_from) * uf.size(bridge_to)
    uf.union(bridge_from,bridge_to)

for i in range(1,M+1):
    print(output_list[i])