Problem:
 Score : 400 points    Problem Statement There are N persons called Person 1 through Person N .  You are given M facts that "Person A_i and Person B_i are friends." The same fact may be given multiple times.  If X and Y are friends, and Y and Z are friends, then X and Z are also friends. There is no friendship that cannot be derived from the M given facts.  Takahashi the evil wants to divide the N persons into some number of groups so that every person has no friend in his/her group.  At least how many groups does he need to make?      Constraints  2 \leq N \leq 2\times 10^5  0 \leq M \leq 2\times 10^5  1\leq A_i,B_i\leq N  A_i \neq B_i         Input Input is given from Standard Input in the following format:  N  M  A_1  B_1  \vdots  A_M  B_M       Output Print the answer.        Sample Input 1 5 3
1 2
3 4
5 1      Sample Output 1 3  Dividing them into three groups such as \{1,3\} , \{2,4\} , and \{5\} achieves the goal.       Sample Input 2 4 10
1 2
2 1
1 2
2 1
1 2
1 3
1 4
2 3
2 4
3 4      Sample Output 2 4       Sample Input 3 10 4
3 1
4 1
5 9
2 6      Sample Output 3 3

Solution (Python):
class UnionFind:
    def __init__(self, sz: int):
        self._par: list[int] = [-1] * sz

    def root(self, a: int):
        if self._par[a] < 0:
            return a
        self._par[a] = self.root(self._par[a])
        return self._par[a]
    
    def size(self, a: int):
        return -self._par[self.root(a)]
    
    def unite(self, a, b):
        a = self.root(a)
        b = self.root(b)
        if a != b:
            if self.size(a) < self.size(b):
                a, b = b, a
            self._par[a] += self._par[b]
            self._par[b] = a
    
if __name__ == '__main__':
    N, M = map(int, input().split())
    uf = UnionFind(N + 1)
    for i in range(M):
        a, b = map(int, input().split())
        uf.unite(a, b)
    ans = 1
    for i in range(1, N + 1):
        ans = max(ans, uf.size(i))
    print(ans)

Solution (Python):
class UnionFind:
    
    def __init__(self, n):
        
        self.par = [-1] * n
    
    
    def root(self, x):
        
        if self.par[x] < 0:
            return x
        
        self.par[x] = self.root(self.par[x])    
        return self.par[x]

    
    def union(self, x, y):
        x = self.root(x)
        y = self.root(y)
        
        if x == y:
            return
        
        if self.par[x] > self.par[y]:   
            x, y = y, x
        self.par[x] += self.par[y]
        self.par[y] = x
    
    
    def size(self, x):
        return -1 * self.par[self.root(x)]



n, m = map(int, input().split())
uf = UnionFind(n)

for _ in range(m):
    a, b = map(int, input().split())
    uf.union(a-1, b-1)      

ans = 0
for i in range(n):
    ans = max(ans, uf.size(i))
print(ans)

Solution (Python):
N,M = tuple(map(int,input().split()))


friendlist = list(range(N))

gplist = [[i] for i in range(N)]

def getgroup(a):
    A = friendlist[a]
    if A == a:
        return a
    else:
        return getgroup(A)

def match(ab):
    A = getgroup(ab[0])
    B = getgroup(ab[1])
    if A==B:
        return
    elif len(gplist[A])<len(gplist[B]):
        gplist[B].extend(gplist[A])
        friendlist[A] = B
    else:
        gplist[A].extend(gplist[B])
        friendlist[B] = A

for i in range(M):
    
    
    match(tuple(map(lambda x:int(x)-1,input().split())))




print(max([len(item) for item in gplist]))

Solution (Python):
from collections import deque

N, M = map(int, input().split())
friends = [[] for _ in range(N+1)]
for __ in range(M):
  a, b = map(int, input().split())
  friends[a].append(b)
  friends[b].append(a)
checked = [0 for ___ in range(N+1)]
answer = 1
for i in range(1, N+1):
  friend = deque(friends[i])
  cnt = 0
  while(len(friend) > 0):
    f = friend.popleft()
    if checked[f] != 0:
      continue
    else:
      checked[f] = 1
      cnt += 1
      for ff in friends[f]:
        friend.append(ff)
  answer = max(answer, cnt)
print(answer)

Solution (Python):
import sys
sys.setrecursionlimit(4100000)
import math
import itertools
INF = float('inf')
from heapq import heapify, heappop, heappush
import collections


n,m = map(int, input().split())
par = [i for i in range(n)]
rank = [0]*n

def find(x):
    if par[x] == x:
        return x
    else:
        par[x] = find(par[x])
        return par[x]

def unite(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        return
    if rank[x] < rank[y]:
        par[x] = y
    else:
        par[y] = x
        if rank[x] == rank[y]:
            rank[x] += 1

def main():
    for _ in range(m):
        a,b = map(int, input().split())
        unite(a-1,b-1)

    count = [0]*n
    for p in par:
        count[find(p)] += 1
    print(max(count))


if __name__ == '__main__':
    main()

Solution (Python):



def find(x):
    if par[x] < 0:
        return x
    else:
        tank = []
        while par[x] >= 0:
            tank.append(x)
            x = par[x]
        for elt in tank:
            par[elt] = x
        return x

def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True


def same(x,y):
    return find(x) == find(y)


def size(x):
    return -par[find(x)]

import sys
input = sys.stdin.buffer.readline
 
n,m = map(int,input().split())



par = [-1]*n

 
for _ in range(m):
    a,b = map(int,input().split())
    unite(a-1,b-1)
 
res = 0
for e in par:
    if e < 0:
        res = max(res,-e)
print(res)

Solution (Python):
def main():
    class unionfind():
        
        def __init__(self, size):  
            self.size = size
            self.tree_root = list(range(self.size))
            self.tree_depth = [1]*self.size

        
        def root(self, index):
            temp_list = []
            temp = self.tree_root[index]
            while index != temp:
                temp_list.append(index)
                index = temp
                temp = self.tree_root[index]
            for i in temp_list:
                self.tree_root[i] = index
            return index

        
        def unite(self, index1, index2):
            r1 = self.root(index1)
            r2 = self.root(index2)
            if r1 != r2:
                d1, d2 = self.tree_depth[r1], self.tree_depth[r2]
                if d1 <= d2:
                    self.tree_root[r1] = r2
                    self.tree_depth[r2] = max(d1+1, d2)
                else:
                    self.tree_root[r2] = r1
                    self.tree_depth[r1] = max(d2+1, d1)

        
        def same(self, index1, index2):
            r1 = self.root(index1)
            r2 = self.root(index2)
            return r1 == r2

        
        def component(self):
            return len({self.root(i) for i in range(self.size)})

    n, m = map(int, input().split())
    ab = [list(map(int, input().split())) for _ in [0]*m]
    s = [0]*n
    uf = unionfind(n)

    for a, b in ab:
        uf.unite(a-1, b-1)

    for i in range(n):
        s[uf.root(i)] += 1
    print(max(s))


main()

Solution (Python):
from collections import Counter



import sys
sys.setrecursionlimit(10 ** 9)

def main(N, M, C):
    lst = [n for n in range(N)] 

    def get_root(x):    
        if lst[x] == x: 
            return x
        else:   
            lst[x] = get_root(lst[x])   
            return lst[x]
            

    def unite(x, y):    
        root_x = get_root(x)
        root_y = get_root(y)
        if root_x != root_y:    
            lst[root_x] = root_y
            
    {unite(*c) for c in C}  
    print(max(Counter(map(get_root, lst)).values()))    


if __name__ == '__main__':
    N, M = list(map(int, input().split()))
    C = set()
    for _ in range(M):
        C.add(tuple(map(lambda x:int(x)-1, input().split())))   
    main(N, M, C)

Solution (Python):
from collections import Counter


import sys
sys.setrecursionlimit(10 ** 9)

def main(N, M, C):
    lst = [n for n in range(N)] 

    def get_root(x):    
        if lst[x] == x: 
            return x
        else:   
            lst[x] = get_root(lst[x])   
            return lst[x]
            

    def unite(x, y):    
        root_x = get_root(x)
        root_y = get_root(y)
        if root_x != root_y:    
            lst[root_x] = root_y

    {unite(*c) for c in C}  

    print(max(Counter(map(get_root, lst)).values()))


if __name__ == '__main__':
    N, M = list(map(int, input().split()))
    C = set()
    for _ in range(M):
        C.add(tuple(map(lambda x:int(x)-1, input().split())))   
    main(N, M, C)

Solution (Python):
import sys
from collections import deque
mapin = lambda: map(int, sys.stdin.readline().split())
listin = lambda: list(map(int, sys.stdin.readline().split()))
inp = lambda: sys.stdin.readline()

class UnionFind():
    def __init__(self,n):
        self.N = n
        self.par = [-1] * n
    
    def find(self,n):
        if self.par[n] < 0:
            return n
        else:
            self.par[n] = self.find(self.par[n])
            return self.par[n]
    
    def unite(self,x,y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return False
        else:
            if -self.par[x] < -self.par[y]:
                x,y = y,x
            self.par[x] += self.par[y]
            self.par[y] = x
    
    def size(self,x):
        return -self.par[self.find(x)]
    
    def tree_num(self):
        res = 0
        for i in self.par:
            res += i < 0
        return res
    
    def same(self,x,y):
        return self.find(x) == self.find(y)
    
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

N,M = mapin()
UF = UnionFind(N)
for i in range(M):
    a,b = mapin()
    a,b = a - 1,b - 1
    UF.unite(a,b)
ans = 0
for i in UF.par:
    if i < 0:
        if ans < -i:
            ans = -i
print(ans)

Solution (Python):
import sys
from collections import deque
mapin = lambda: map(int, sys.stdin.readline().split())
listin = lambda: list(map(int, sys.stdin.readline().split()))
inp = lambda: sys.stdin.readline()

class UnionFind():
    def __init__(self,n):
        self.N = n
        self.par = [-1] * n
    
    def find(self,n):
        if self.par[n] < 0:
            return n
        else:
            self.par[n] = self.find(self.par[n])
            return self.par[n]
    
    def unite(self,x,y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return False
        else:
            if -self.par[x] < -self.par[y]:
                x,y = y,x
            self.par[x] += self.par[y]
            self.par[y] = x
    
    def size(self,x):
        return -self.par[self.find(x)]
    
    def tree_num(self):
        res = 0
        for i in self.par:
            res += i < 0
        return res
    
    def same(self,x,y):
        return self.find(x) == self.find(y)
    
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

N,M = mapin()
UF = UnionFind(N)
for i in range(M):
    a,b = mapin()
    a,b = a - 1,b - 1
    UF.unite(a,b)
ans = 0
for i in UF.par:
    if i < 0:
        if ans < -i:
            ans = -i
print(ans)

Solution (Python):
n, m = map(int, input().split())

class UnionFind:
    def __init__(self, n):
        self.pare = [-1] * n
        self.size = [1] * n
    def root(self, x):
        if self.pare[x] < 0:
            return x
        r = self.root(self.pare[x])
        self.pare[x] = r
        return r
    def unite(self, x, y):
        rx = self.root(x)
        ry = self.root(y)
        if rx == ry:
            return
        self.pare[rx] = ry
        self.size[ry] += self.size[rx]
        return

uf = UnionFind(n)

for i in range(m):
    a, b = map(int, input().split())
    a -= 1
    b -= 1
    uf.unite(a, b)

print(max(uf.size))

Solution (Python):
import sys
input = sys.stdin.readline

N, M = map(int, input().split())
edges = {}
for _ in range(M):
  a, b = map(int, input().split())
  a -= 1
  b -= 1
  if a not in edges:
    edges[a] = set()
  if b not in edges:
    edges[b] = set()
  edges[a].add(b)
  edges[b].add(a)

to_check = set(range(N))
max_size = 0
while to_check:
  checked = set()
  s = set()
  s.add(next(iter(to_check)))
  
  while s:
    current = s.pop()
    checked.add(current)
    if current in edges:
      for n in edges[current]:
        if n not in checked:
          s.add(n)
  max_size = max(max_size, len(checked))
  
  for c in checked:
    to_check.remove(c)
print(max_size)

Solution (Python):

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.root = [-1] * (n + 1)
        
    def find(self, x):
        if self.root[x] < 0:
            return x
        else:
            self.root[x] = self.find(self.root[x])
            return self.root[x]
    
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return False
        if self.root[x] > self.root[y]:
            x, y = y, x
        self.root[x] += self.root[y]
        self.root[y] = x
        
    def is_same(self, x, y):
        return self.find(x) == self.find(y)
    
    def size(self, x):
        return -self.root[self.find(x)]

n, m = map(int, input().split())
friends = UnionFind(n)
for i in range(m):
    a, b = map(int, input().split())
    friends.unite(a, b)
print(max(friends.size(i) for i in range(n)))

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            li = []
            while self.parents[x] >= 0:
                li.append(x)
                x = self.parents[x]
            for y in li:
                self.parents[y] = x
            return 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 size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    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 group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

import sys
input = sys.stdin.buffer.readline
N,M = map(int,input().split())
uf = UnionFind(N)
for i in range(M):
    A,B = map(int,input().split())
    uf.union(A-1,B-1)
ans = 0
for i in uf.roots():
    ans = max(uf.size(i),ans)
print(ans)

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    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 size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    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 group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

import sys
input = sys.stdin.buffer.readline
N,M = map(int,input().split())
uf = UnionFind(N)
for i in range(M):
    A,B = map(int,input().split())
    uf.union(A-1,B-1)
ans = 0
for i in uf.roots():
    ans = max(uf.size(i),ans)
print(ans)

Solution (Python):

_INPUT = """\
5 3
1 2
3 4
5 1
"""
"""
K = int(input())
H, W, K = map(int, input().split())
a = list(map(int, input().split()))
xy = [list(map(int, input().split())) for i in range(N)]
p = tuple(map(int,input().split()))
"""
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    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 size(self, x):
        return -self.parents[self.find(x)]



def main():
    n, m = map(int, input().split())
    xy = [list(map(int, input().split())) for i in range(m)]

    uf = UnionFind(n)

    for i in range(len(xy)):
        uf.union(xy[i][0]-1,xy[i][1]-1)
    
    print(-(min(uf.parents)))

    
    
    

            
if __name__ == '__main__':
    import io
    import sys
    import math
    import itertools
    from collections import deque

    
    main()

Solution (Python):
n,m=map(int,input().split())



par=[i for i in range(n)]
deep=[1]*n
size=[1]*n


def find(x):
  if par[x]==x:
    return x
  else:
    return find(par[x])


def unite(x,y):
  x=find(x)
  y=find(y)
  if x==y:
    return
  if deep[x]<deep[y]:
    par[x]=y
    size[y]+=size[x]
  else:
    par[y]=x
    size[x]+=size[y]
    if deep[x]==deep[y]:
      deep[x]+=1


def same(x,y):
  return find(x)==find(y)


for i in range(m):
  a,b=map(int,input().split())
  unite(a-1,b-1)
print(max(size))

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n
 
    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 size(self, x):
        return -self.parents[self.find(x)]
 
    def same(self, x, y):
        return self.find(x) == self.find(y)
 
    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 group_count(self):
        return len(self.roots())
 
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
 
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
 
nm = list(map(int, input().split()))
n = nm[0]
m = nm[1]
 
ans = 1
 
uf = UnionFind(n)
for i in range(m):
    friends = list(map(int, input().split()))
    uf.union(friends[0]-1,friends[1]-1)
    if ans < uf.size(friends[1]-1):
        ans = uf.size(friends[1]-1)
print(ans)

Solution (Python):
class UnionFind():
  def __init__(self, n):
    self.n = n
    self.parents = [-1] * n
  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 size(self, x):
    return -self.parents[self.find(x)]
  def same(self, x, y):
    return self.find(x) == self.find(y)
  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 group_count(self):
    return len(self.roots())
  def all_group_members(self):
    return {r: self.members(r) for r in self.roots()}
  def __str__(self):
    return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
      
N,M=map(int,input().split())
U=UnionFind(N)
for m in range(M):
  a,b=map(int,input().split())
  U.union(a-1,b-1)
ans=0
for i in U.roots():
  ans=max(ans,U.size(i))
print(ans)

Solution (Python):
from collections import deque

n, m = map(int, input().split())

graph = [[] for _ in range(n+1)]

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

dist = [-1] * (n+1)
dist[0] = 0


d = deque()
ans = 1
for j in range(len(dist)):
    if dist[j] != -1:
        continue
    d.append(j)
    cnt = 0
    while d:
        v = d.popleft()
        for i in graph[v]:
            if dist[i] != -1:
                continue
            dist[i] = dist[v] + 1
            d.append(i)
            cnt = cnt + 1
    ans = max(ans,cnt)

print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n=0):
        self.d = [-1]*n
    def find(self, x):
        if self.d[x] < 0:
            return x
        else:
            self.d[x] = self.find(self.d[x])
            return self.d[x]
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return False
        if self.d[x] > self.d[y]:
            x, y = y, x
        self.d[x] += self.d[y]
        self.d[y] = x
        return True
    def same(self, x, y):
        return self.find(x) == self.find(y)
    def size(self, x):
        return -self.d[self.find(x)]

n, m = map(int, input().split())

uf = UnionFind(n)
for _ in range(m):
    a, b = map(int, input().split())
    a -= 1
    b -= 1
    uf.unite(a, b)

ans = 1
for i in range(n):
    ans = max(ans, uf.size(i))
print(ans)

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n
    
    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 unite(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 size(self, x):
        return -self.parents[self.find(x)]
    
    def isSame(self, x, y):
        return self.find(x) == self.find(y)

def solve():
    N,M = map(int,input().split())
    uf = UnionFind(N)
    for _ in range(M):
        a,b = map(int,input().split())
        a -= 1
        b -= 1

        uf.unite(a,b)
    
    ans = 0
    for i in range(N):
        ans = max(ans,uf.size(i))
    
    print(ans)
        
if __name__ == '__main__':
    solve()

Solution (Python):
import bisect, collections, copy, heapq, itertools, math, string, sys
input = lambda: sys.stdin.readline().rstrip() 
sys.setrecursionlimit(10**7)
INF = float('inf')
def I(): return int(input())
def F(): return float(input())
def SS(): return input()
def LI(): return [int(x) for x in input().split()]
def LI_(): return [int(x)-1 for x in input().split()]
def LF(): return [float(x) for x in input().split()]
def LSS(): return input().split()

def resolve():
    N, M = LI()
    G = collections.defaultdict(set)
    for _ in range(M):
        A, B = LI_()
        G[A].add(B)
        G[B].add(A)
    

    
    visited = [False] * N
    def dfs(c, cnt):
        visited[c] = True
        cnt[0] += 1
        for n in G[c]:
            if not visited[n]:
                dfs(n, cnt)

    ans = 0
    for i in range(N):
        cnt = [0]
        dfs(i, cnt)
        ans = max(cnt[0], ans)

    print(ans)

if __name__ == '__main__':
    resolve()

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    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 size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    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 group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
N,M = map(int,input().split())
A=[]
B=[]
for i in range(M):
    n,a=input().split()
    A.append(int(n))
    B.append(int(a))
uf = UnionFind(N)
for i in range(len(A)):
    uf.union(A[i]-1,B[i]-1)
ans=0
for i in range(N):
    ans=max(ans,uf.size(i))
print(ans)

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    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 size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    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 group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

n, m = map(int, input().split())
ab = [list(map(int, input().split())) for _ in range(m)]
uf = UnionFind(n)
for i in range(m):
    x, y = ab[i][0], ab[i][1]
    x -= 1
    y -= 1
    uf.union(x, y)
ans = 0
for i in range(n):
    ans = max(uf.size(i), ans)
print(ans)

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    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 size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    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 group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


N, M = map(int, input().split())
uf = UnionFind(N)

ans = 0
for i in range(M):
    A, B = map(int, input().split())
    uf.union(A-1, B-1)

for i in range(uf.group_count()):
    if ans < uf.size(i):
        ans = uf.size(i)
print(ans)

Solution (Python):
import sys
input = sys.stdin.readline

class UnionFind():
    def __init__(self, N):
        self.N = N
        self.r = [-1] * (N+1)

    def root(self, x):
        if (self.r[x] < 0):
            return x
        else:
            self.r[x] = self.root(self.r[x])
            return self.r[x]

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.r[x] > self.r[y]:
            x, y = y, x
        self.r[x] += self.r[y]
        self.r[y] = x
        return True

    def size(self, x):
        return -self.r[self.root(x)]

    def same(self, x, y):
        return self.root(x) == self.root(y)

def main():
    N, M = map(int, input().split())
    uf = UnionFind(N)
    for _ in range(M):
        A, B = map(lambda i: int(i)-1, input().split())
        uf.unite(A, B)

    ans = 0
    for i in range(N):
        ans = max(ans, uf.size(i))

    print(ans)

main()

Solution (Python):
def find(x):
    if par[x]==x:
        return x
    else:
        par[x]=find(par[x])
        return par[x]
def unite(x,y):
    x=find(x)
    y=find(y)
    if x == y:
        return 0
    if x<y:x,y=y,x    
    par[x]=y
n,m=map(int,input().split())
par=[i for i in range(n+1)]
for _ in range(m):
    i,j=map(int,input().split())
    unite(i,j)
ans=[0]*(n+1)
for i in range(n+1):
    find(i)
for i in par:
    ans[i]+=1
print(max(ans))

Solution (Python):
import sys
sys.setrecursionlimit(10**6)

class UnionFind:

    def __init__(self, n: int) -> None:
        self.p = [-1] * n
        self.r = [1] * n

    def find(self, x: int) -> int:
        if(self.p[x] == -1): return x
        self.p[x] = self.find(self.p[x])
        
        return self.p[x]

    def unite(self, x: int, y: int) -> None:
        x = self.find(x)
        y = self.find(y)
        if(x == y): return
        if(self.r[x] > self.r[y]): x, y = y, x
        if(self.r[x] == self.r[y]): self.r[y] += 1

        self.p[x] = y
    
    def same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)

    
    

def main():
    n, m = map(int, input().split())

    uf = UnionFind(n)
    for _ in range(m):
        a, b = map(int, input().split())
        a -= 1
        b -= 1
        
        uf.unite(a, b)
    
    group = {}

    res = 0
    for i in range(n):
        g = uf.find(i)
        
        if(group.get(g) is None): group[g] = 1
        else: group[g] += 1

        res = max(res, group[g])
    
    print(res)

    


if __name__ == "__main__":
    main()

Solution (Python):
class UnionFind():
    def __init__(self,n):
        self.parents = [-1]*n

    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
        
N,M = map(int,input().split())    
uf = UnionFind(N)

for i in range(M):
    A,B = map(lambda x:int(x)-1,input().split())
    uf.union(A,B)
    

print(abs(min(uf.parents)))