Buggy python submission (verdict: Time Limit Exceeded):
def union(group, new_mem):
    if  (group[new_mem[0]-1] * group[new_mem[1]-1]) < 0: 
        choice = max(group[new_mem[0]-1], group[new_mem[1]-1])
       
        for i in range(len(new_mem)):
            group[new_mem[i]-1] = choice
            
    elif group[new_mem[0]-1] <0 and group[new_mem[1]-1] < 0:
        for i in range(len(new_mem)):
            group[new_mem[i]-1] = min(new_mem[0], new_mem[1])
        
    elif (group[new_mem[0]-1] != group[new_mem[1]-1])  and (group[new_mem[0]-1] * group[new_mem[1]-1]) > 0: 
        old = max(group[new_mem[0]-1], group[new_mem[1]-1])
        new = min(group[new_mem[0]-1], group[new_mem[1]-1])
        for i in range(len(group)):
            if group[i] == old:
                group[i] = new
                 
    return group

def find(group, v):
    return group[v-1]

def size(group, v):
    input_v = find(group, v)
    return group.count(input_v)
    
n,m = map(int, input().split())
bridge = []
for i in range(m):
    a, b= map(int, input().split())
    bridge.append((a,b))

non_route = []
total = int(n*(n-1)/2)
non_route.append(total)

group = [-i  for i in range(1, n+1)] 
tmp = total
group_before = group.copy()
for i in range(m-1,0,-1):
    group = union(group, bridge[i]) 
    
    if find(group_before,bridge[i][0]) == find(group_before, bridge[i][1]):
        non_route.append(tmp)
    else:
        n_1 = size(group_before, bridge[i][0])
        n_2 = size(group_before, bridge[i][1])
        tmp -=   n_1 * n_2
        non_route.append(tmp)
    group_before = group.copy()

final = sorted(non_route)
for i in range(len(final)):
    print(final[i])

Fixed submission:
class UnionFind:
    def __init__(self, size):
        self.parent = [-1 for i in range(size)]#非負なら親ノード，負ならグループの要素数
 
    def root(self, x): #root(x): xの根ノードを返す．
        if self.parent[x] < 0:
            return x
        else:
            self.parent[x] = self.root(self.parent[x]) #xをxの根に直接つなぐ
            return self.parent[x]
 
    def merge(self, x, y): #merge(x,y): xのいるグループと$y$のいるグループをまとめる
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.parent[x] > self.parent[y]: #xの要素数がyの要素数より「小さい」とき入れ替える
            x,y=y,x
        self.parent[x] += self.parent[y] #xの要素数を更新
        self.parent[y] = x #yをxにつなぐ
        return True
 
    def issame(self, x, y): #same(x,y): xとyが同じグループにあるならTrue
        return self.root(x) == self.root(y)
        
    def size(self,x): #size(x): xのいるグループの要素数を返す
        return -self.parent[self.root(x)]
    
n,m = map(int, input().split())
bridge = []
for i in range(m):
    a, b= map(int, input().split())
    bridge.append((a,b))

non_route = []
total = int(n*(n-1)/2)
non_route.append(total)

uft = UnionFind(n)

tmp = total

for i in range(m-1,0,-1):
    a = bridge[i][0] -1
    b = bridge[i][1] -1

    if uft.issame(a, b):
        non_route.append(non_route[-1])
        continue
    ra = uft.size(a)
    rb = uft.size(b)
    non_route.append(non_route[-1] - ra * rb)
    uft.merge(a, b)

final = sorted(non_route)
for i in range(len(final)):
    print(final[i])

Buggy python submission (verdict: Time Limit Exceeded):
def union(group, new_mem):
    if (group[new_mem[0]-1] + group[new_mem[1]-1]) != 0 and (group[new_mem[0]-1] * group[new_mem[1]-1]) == 0:
        choice = max(group[new_mem[0]-1], group[new_mem[1]-1])
       
        group[new_mem[0]-1] = choice
        group[new_mem[1]-1] = choice
            
    elif group[new_mem[0]-1] + group[new_mem[1]-1] == 0: 

        group[new_mem[0]-1] = min(new_mem[0], new_mem[1])
        group[new_mem[1]-1] = min(new_mem[0], new_mem[1])
        
    elif (group[new_mem[0]-1] + group[new_mem[1]-1]) != 0 and (group[new_mem[0]-1] * group[new_mem[1]-1]) != 0:
        old = max(group[new_mem[0]-1], group[new_mem[1]-1])
        new = min(group[new_mem[0]-1], group[new_mem[1]-1])
        for i in range(len(group)):
            if group[i] == old:
                group[i] = new
                 
    return group

n,m = map(int, input().split())
bridge = []
for i in range(m):
    a, b= map(int, input().split())
    bridge.append((a,b))

non_route = []
total = int(n*(n-1)/2)
non_route.append(total)

group = [0 for i in range(n)] 
for i in range(m-1,0,-1):
    group_for_calc = union(group, bridge[i]) 
    connected_group = list(set(group_for_calc)-set({0})) 
    count = 0
    if len(connected_group) == 1:
        num = group_for_calc.count(connected_group[0])
        count = int(num*(num-1)/2)

    else:
        for i in range(len(connected_group)):
            num = group_for_calc.count(connected_group[i])
            count += int(num*(num-1)/2)
    ans = total - count
    non_route.append(ans)

final = sorted(non_route)
for i in range(len(final)):
    print(final[i])

Fixed submission:
class UnionFind:
    def __init__(self, size):
        self.parent = [-1 for i in range(size)]#非負なら親ノード，負ならグループの要素数
 
    def root(self, x): #root(x): xの根ノードを返す．
        if self.parent[x] < 0:
            return x
        else:
            self.parent[x] = self.root(self.parent[x]) #xをxの根に直接つなぐ
            return self.parent[x]
 
    def merge(self, x, y): #merge(x,y): xのいるグループと$y$のいるグループをまとめる
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.parent[x] > self.parent[y]: #xの要素数がyの要素数より「小さい」とき入れ替える
            x,y=y,x
        self.parent[x] += self.parent[y] #xの要素数を更新
        self.parent[y] = x #yをxにつなぐ
        return True
 
    def issame(self, x, y): #same(x,y): xとyが同じグループにあるならTrue
        return self.root(x) == self.root(y)
        
    def size(self,x): #size(x): xのいるグループの要素数を返す
        return -self.parent[self.root(x)]
    
n,m = map(int, input().split())
bridge = []
for i in range(m):
    a, b= map(int, input().split())
    bridge.append((a,b))

non_route = []
total = int(n*(n-1)/2)
non_route.append(total)

uft = UnionFind(n)

tmp = total

for i in range(m-1,0,-1):
    a = bridge[i][0] -1
    b = bridge[i][1] -1

    if uft.issame(a, b):
        non_route.append(non_route[-1])
        continue
    ra = uft.size(a)
    rb = uft.size(b)
    non_route.append(non_route[-1] - ra * rb)
    uft.merge(a, b)

final = sorted(non_route)
for i in range(len(final)):
    print(final[i])

Buggy python submission (verdict: Time Limit Exceeded):
def union(group, new_mem):
    if (group[new_mem[0]-1] + group[new_mem[1]-1]) != 0 and (group[new_mem[0]-1] * group[new_mem[1]-1]) == 0:
        choice = max(group[new_mem[0]-1], group[new_mem[1]-1])
       
        for i in range(len(new_mem)):
            group[new_mem[i]-1] = choice
            
    elif group[new_mem[0]-1] + group[new_mem[1]-1] == 0: 
        for i in range(len(new_mem)):
            group[new_mem[i]-1] = min(new_mem[0], new_mem[1])
        
    elif (group[new_mem[0]-1] + group[new_mem[1]-1]) != 0 and (group[new_mem[0]-1] * group[new_mem[1]-1]) != 0:
        old = max(group[new_mem[0]-1], group[new_mem[1]-1])
        new = min(group[new_mem[0]-1], group[new_mem[1]-1])
        for i in range(len(group)):
            if group[i] == old:
                group[i] = new
                 
    return group

n,m = map(int, input().split())
bridge = []
for i in range(m):
    a, b= map(int, input().split())
    bridge.append((a,b))

non_route = []
total = int(n*(n-1)/2)
non_route.append(total)

group = [0 for i in range(n)] 
for i in range(m-1,0,-1):
    group_for_calc = union(group, bridge[i]) 
    connected_group = list(set(group_for_calc)-set({0})) 
    count = 0
    for i in range(len(connected_group)):
        num = group_for_calc.count(connected_group[i])
        count += int(num*(num-1)/2)
    ans = total - count
    non_route.append(ans)

final = sorted(non_route)
for i in range(len(final)):
    print(final[i])

Fixed submission:
class UnionFind:
    def __init__(self, size):
        self.parent = [-1 for i in range(size)]#非負なら親ノード，負ならグループの要素数
 
    def root(self, x): #root(x): xの根ノードを返す．
        if self.parent[x] < 0:
            return x
        else:
            self.parent[x] = self.root(self.parent[x]) #xをxの根に直接つなぐ
            return self.parent[x]
 
    def merge(self, x, y): #merge(x,y): xのいるグループと$y$のいるグループをまとめる
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.parent[x] > self.parent[y]: #xの要素数がyの要素数より「小さい」とき入れ替える
            x,y=y,x
        self.parent[x] += self.parent[y] #xの要素数を更新
        self.parent[y] = x #yをxにつなぐ
        return True
 
    def issame(self, x, y): #same(x,y): xとyが同じグループにあるならTrue
        return self.root(x) == self.root(y)
        
    def size(self,x): #size(x): xのいるグループの要素数を返す
        return -self.parent[self.root(x)]
    
n,m = map(int, input().split())
bridge = []
for i in range(m):
    a, b= map(int, input().split())
    bridge.append((a,b))

non_route = []
total = int(n*(n-1)/2)
non_route.append(total)

uft = UnionFind(n)

tmp = total

for i in range(m-1,0,-1):
    a = bridge[i][0] -1
    b = bridge[i][1] -1

    if uft.issame(a, b):
        non_route.append(non_route[-1])
        continue
    ra = uft.size(a)
    rb = uft.size(b)
    non_route.append(non_route[-1] - ra * rb)
    uft.merge(a, b)

final = sorted(non_route)
for i in range(len(final)):
    print(final[i])