Buggy python submission (verdict: Runtime Error):
n,m=map(int, input().split())

roads=[]

for _ in range(m):
  a,b=map(int, input().split())
  if a<b:
  	roads.append([a,b].sort())
  else:
    roads.append([b,a].sort())
  
group=[i for i in range(n)]

group2=[]

while group2!=group:
  group2=group
  for road in roads:
    group[road[1]-1]=group[road[0]-1]

counter=1
for i in range(n-1):
  if group[i]!=group[i+1]:
    counter+=1

print(counter-1) 
      

Fixed submission:
class UnionFind:
    from typing import List, Set

    def __init__(self, n):
        self.n = n
        self.parent = [-1] * n

    def merge(self, x, y) -> int:
        x = self.leader(x)
        y = self.leader(y)

        if x == y:
            return 0

        if self.parent[x] > self.parent[y]:
            x, y = y, x

        self.parent[x] += self.parent[y]
        self.parent[y] = x

        return self.parent[x]

    def same(self, x, y) -> bool:
        return self.leader(x) == self.leader(y)

    def leader(self, x) -> int:
        if self.parent[x] < 0:
            return x
        else:
            self.parent[x] = self.leader(self.parent[x])
            return self.parent[x]

    def size(self, x) -> int:
        return -self.parent[self.leader(x)]

    def groups(self) -> List[Set[int]]:
        groups = dict()

        for i in range(self.n):
            p = self.leader(i)
            if not groups.get(p):
                groups[p] = set()
            groups[p].add(i)

        return list(groups.values())


def main():
    N, M = map(int, input().split())

    uf = UnionFind(N)

    for _ in range(M):
        # UnionFindを0スタートで実装しているので、入力から1引きます
        A, B = map(lambda x: int(x) - 1, input().split())  
        uf.merge(A, B)  # AとBをmergeします。union, uniteとも呼ばれます。

    print(len(uf.groups()) - 1)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Runtime Error):
n,m=map(int, input().split())

roads=[]

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

group2=[]

while group2!=group:
  group2=group
  for road in roads:
    group[road[1]-1]=group[road[0]-1]

counter=1
for i in range(n-1):
  if group[i]!=group[i+1]:
    counter+=1
    
print(counter-1) 
      

Fixed submission:
class UnionFind:
    from typing import List, Set

    def __init__(self, n):
        self.n = n
        self.parent = [-1] * n

    def merge(self, x, y) -> int:
        x = self.leader(x)
        y = self.leader(y)

        if x == y:
            return 0

        if self.parent[x] > self.parent[y]:
            x, y = y, x

        self.parent[x] += self.parent[y]
        self.parent[y] = x

        return self.parent[x]

    def same(self, x, y) -> bool:
        return self.leader(x) == self.leader(y)

    def leader(self, x) -> int:
        if self.parent[x] < 0:
            return x
        else:
            self.parent[x] = self.leader(self.parent[x])
            return self.parent[x]

    def size(self, x) -> int:
        return -self.parent[self.leader(x)]

    def groups(self) -> List[Set[int]]:
        groups = dict()

        for i in range(self.n):
            p = self.leader(i)
            if not groups.get(p):
                groups[p] = set()
            groups[p].add(i)

        return list(groups.values())


def main():
    N, M = map(int, input().split())

    uf = UnionFind(N)

    for _ in range(M):
        # UnionFindを0スタートで実装しているので、入力から1引きます
        A, B = map(lambda x: int(x) - 1, input().split())  
        uf.merge(A, B)  # AとBをmergeします。union, uniteとも呼ばれます。

    print(len(uf.groups()) - 1)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Runtime Error):
n,m=map(int, input().split())

roads=[]

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

group2=[]

while group2!=group:
  group2=group
  for road in roads:
    group[road[1]]=group[road[0]]

print(group[-1])  
      

Fixed submission:
class UnionFind:
    from typing import List, Set

    def __init__(self, n):
        self.n = n
        self.parent = [-1] * n

    def merge(self, x, y) -> int:
        x = self.leader(x)
        y = self.leader(y)

        if x == y:
            return 0

        if self.parent[x] > self.parent[y]:
            x, y = y, x

        self.parent[x] += self.parent[y]
        self.parent[y] = x

        return self.parent[x]

    def same(self, x, y) -> bool:
        return self.leader(x) == self.leader(y)

    def leader(self, x) -> int:
        if self.parent[x] < 0:
            return x
        else:
            self.parent[x] = self.leader(self.parent[x])
            return self.parent[x]

    def size(self, x) -> int:
        return -self.parent[self.leader(x)]

    def groups(self) -> List[Set[int]]:
        groups = dict()

        for i in range(self.n):
            p = self.leader(i)
            if not groups.get(p):
                groups[p] = set()
            groups[p].add(i)

        return list(groups.values())


def main():
    N, M = map(int, input().split())

    uf = UnionFind(N)

    for _ in range(M):
        # UnionFindを0スタートで実装しているので、入力から1引きます
        A, B = map(lambda x: int(x) - 1, input().split())  
        uf.merge(A, B)  # AとBをmergeします。union, uniteとも呼ばれます。

    print(len(uf.groups()) - 1)


if __name__ == '__main__':
    main()