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

class UnionFind:
    def __init__(self, element_count):
        self.parent = [i for i in range(element_count)]
        self.counter = [1 for _ in range(element_count)]
    
    def root(self, index):
        root = index
        while root != self.parent[root]:
            root = self.parent[root]
        while index != root:
            index, self.parent[index] = self.parent[index], root
        return root
    
    def unite(self, x, y):
        x, y = self.root(x), self.root(y)
        if x != y:
            self.parent[y] = x
            self.counter[x] += self.counter[y]
            self.counter[y] = 0
    
    def count(self, index):
        return self.counter[self.root(index)]

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

uf = UnionFind(N)
for _ in range(M):
  a, b = map(int, input().split())
  a -= 1
  b -= 1
  uf.unite(a,b)
print(max(uf.counter))

Solution (Python):
import sys, math
from functools import lru_cache
sys.setrecursionlimit(10**9)
MOD = 10**9+7

def input():
    return sys.stdin.readline()[:-1]

def mi():
    return map(int, input().split())

def ii():
    return int(input())

def i2(n):
    tmp = [list(mi()) for i in range(n)]
    return [list(i) for i in zip(*tmp)]


class Uf:
    def __init__(self, N):
        self.p = list(range(N))
        self.rank = [0] * N
        self.size = [1] * N

    def root(self, x):
        if self.p[x] != x:
            self.p[x] = self.root(self.p[x])

        return self.p[x]

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

    def unite(self, x, y):
        u = self.root(x)
        v = self.root(y)

        if u == v: return

        if self.rank[u] < self.rank[v]:
            self.p[u] = v
            self.size[v] += self.size[u]
            self.size[u] = 0
        else:
            self.p[v] = u
            self.size[u] += self.size[v]
            self.size[v] = 0

            if self.rank[u] == self.rank[v]:
                self.rank[u] += 1

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

def main():
    N, M = mi()

    if M == 0:
        print(1)
        return
        
    A, B = i2(M)

    uf = Uf(N)
    for i in range(M):
        uf.unite(A[i]-1, B[i]-1)

    print(max(uf.count(i) for i in range(N)))
    


if __name__ == '__main__':
    main()

Solution (Python):
import sys
def input():
    return sys.stdin.readline()[:-1]
sys.setrecursionlimit(200000)
class uf:
    def __init__(self,n):
        self.n=n
        self.l=[-1]*n
    def ro(self,n):         
        if self.l[n]<0:
            return n
        r=self.ro(self.l[n])
        self.l[n]=r
        return r
    def me(self,a,b):       
        ra=self.ro(a)
        rb=self.ro(b)
        if self.l[ra]>self.l[rb]:
            ra,rb=rb,ra
        if ra!=rb:
            self.l[ra]+=self.l[rb]
            self.l[rb]=ra
    def size(self,n):
        return -self.l[self.ro(n)]
    def sa(self,a,b):       
        return self.ro(a)==self.ro(b)
    def rl(self):           
        return [i for i,v in enumerate(self.l) if v<0]
    
    def len(self):          
        return len(self.rl())
    def ul(self):
        d={n:i for i,n in enumerate(self.rl())}
        m=[[]for i in range(self.len())]
        for i in range(self.n):
            m[d[self.ro(i)]].append(i)
        return m
    def __str__(self):
        return f"{self.ul()}"
    def __setitem__(self,i,v):
        self.l[i]=v
N,M=map(int,input().split())
u=uf(N)
for i in range(M):
    A,B=map(lambda x: int(x)-1,input().split())
    u.me(A,B)
a=0
for i in u.ul():
    t=len(i)
    if t>a:
        a=t
print(a)

Solution (Python):
def main():
    import sys
    input = sys.stdin.readline
    sys.setrecursionlimit(10**7)
    from collections import Counter, deque
    from collections import defaultdict
    from itertools import combinations, permutations, accumulate, groupby, product
    from bisect import bisect_left,bisect_right
    from heapq import heapify, heappop, heappush
    from math import floor, ceil,pi,factorial
    from operator import itemgetter
    def I(): return int(input())
    def MI(): return map(int, input().split())
    def LI(): return list(map(int, input().split()))
    def LI2(): return [int(input()) for i in range(n)]
    def MXI(): return [[LI()]for i in range(n)]
    def SI(): return input().rstrip()
    def printns(x): print('\n'.join(x))
    def printni(x): print('\n'.join(list(map(str,x))))
    inf = 10**17
    mod = 10**9 + 7

    

    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=MI()
    uf=UnionFind(n)
    for i in range(m):
        a,b=MI()
        a-=1
        b-=1
        uf.union(a,b)
    ans=0
    for x in uf.roots():
        ans=max(ans,uf.size(x))
    print(ans)
        
            
        
if __name__=="__main__":
    main()

Solution (Python):
import sys
import heapq
import math
import fractions
import bisect
import itertools
from collections import Counter
from collections import deque
from operator import itemgetter
def input(): return sys.stdin.readline().strip()
def mp(): return map(int,input().split())
def lmp(): return list(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 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=mp()
uf = UnionFind(n+1)
for i in range(m):
    a,b=mp()
    uf.union(a,b)
ans=0
for i in range(n+1):
    ans=max(ans,uf.size(i))
print(ans)

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



def find(x):
    if par[x] < 0:
        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 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)]




par = [-1] * (n + 1)
for _ in range(m):
    a, b = map(int, input().split())
    unite(a, b)
ans = 0
for i in range(1, n + 1):
    ans = max(ans, size(i))
print(ans)

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

p=[-1]*n
def root(x):
  while p[x]>=0: x=p[x]
  return x
def unite(x,y):
  x,y=root(x),root(y)
  if x==y: return
  if x>y: x,y=y,x
  p[x]+=p[y]
  p[y]=x
def same(x,y):
  return root(x)==root(y)
def size(x):
  return -p[root(x)]

for i in range(m):
  a,b=f()
  unite(a-1,b-1)
print(-min(p))

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

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

class UnionFind:
    def __init__(self, n):
        self.par = [-1]*(n+1)
        self.sizes=[1]*(n+1)

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

    
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x==y:
            return
        d1=self.par[x]
        d2=self.par[y]
        if d1<=d2:
            self.par[y]=x
            self.sizes[x]=self.sizes[x]+self.sizes[y]
            if d1==d2:
                self.par[x]=self.par[x]-1
        else:
            self.par[x]=y
            self.sizes[y]=self.sizes[x]+self.sizes[y]

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

    
    def size(self,x):
        return self.sizes[self.find(x)]

    
    def number(self):
        count=0
        for i in self.par[1:]:
            if i<0:
                count=count+1
        return count

U=UnionFind(n)
for _ in range(m):
    a,b=map(int,input().split())
    a-=1
    b-=1
    if not U.same_check(a,b):
        U.union(a,b)

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

Solution (Python):
LI = lambda: list(map(int, input().split()))

N, M = LI()
AB = [LI() for _ in range(M)]


class Node:

    def __init__(self, num):
        self.num = num
        self.parent = None

    def root(self):
        if self.parent is None:
            return self
        self.parent = self.parent.root()
        return self.parent


class UnionFind:

    def __init__(self, n):
        self.n = n
        self.nodes = [Node(i) for i in range(n)]
        self.groups = {i: 1 for i in range(n)}
    
    def unite(self, x, y):
        x = self.nodes[x].root().num
        y = self.nodes[y].root().num
        if x == y:
            return
        if self.groups[x] < self.groups[y]:
            x, y = y, x
        self.groups[x] += self.groups[y]
        del self.groups[y]
        self.nodes[y].parent = self.nodes[x]
    
    def same(self, x, y):
        a = self.nodes[x].root()
        b = self.nodes[y].root()
        return True if a == b else False


def main():
    uf = UnionFind(N)
    for a, b in AB:
        uf.unite(a - 1, b - 1)
    ans = max(uf.groups.values())
    print(ans)


if __name__ == "__main__":
    main()

Solution (Python):
class UnionFind:
    """
    sizeによる実装
    """

    def __init__(self, N):
        self.parent = [i for i in range(N)]
        self.size = [1 for _ in range(N)]

    def find(self, x):
        """
        x: child
        ret-> node
        xのグループの代表を見つける
        """
        if self.parent[x] == x:
            return x
        else:
            return self.find(self.parent[x])

    def union(self, x, y):
        """
        union (x ,y)
        x,y: node
        ret->None
        """
        px = self.find(x)
        py = self.find(y)
        if px == py:
            return
        if self.size[px] < self.size[py]:
            self.parent[px] = py
            self.size[py] += self.size[px]
        else:
            self.parent[py] = px
            self.size[px] += self.size[py]

    def same(self, x, y):
        """
        return true if x and y are in same group
        """
        return self.find(x) == self.find(y)

    def connectedNum(self, x):
        """
        return size of the group x belong to
        """
        return self.size[self.find(x)]

    def is_connected(self):
        """
        return true is all node is in one group
        """
        return self.connectedNum(0) == len(self.parent)

    def conpomentNum(self):
        """
        return num of component
        """
        par_set=set()
        for p in self.parent:
            par_set.add(self.find(p))
        return len(par_set())


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

for _ in range(M):
    a,b = map(lambda x:int(x)-1,input().split())
    Un.union(a,b)

max_size=max(Un.connectedNum(i) for i in range(N))
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):
        '''
        注意：0-idx
        '''
        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)
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):
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 same(self, x, y):                                       
        return self.find(x) == self.find(y)

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

N, M = map(int, input().split())
U = UnionFind(N)
for _ in range(M):
    a, b = map(int, input().split())
    a, b = a-1, b-1
    U.union(a, b)
print(-min(U.parents))

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

n, m = 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 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()}

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 range(n):
    cnt = uf.size(i)
    ans = max(ans, cnt)
print(ans)

Solution (Python):
class DisjointSets:
    def __init__(self, n):
        self.nodes = [-1] * n 
    def find(self, i):
        if self.nodes[i] < 0: 
            return i
        else:
            self.nodes[i] = self.find(self.nodes[i]) 
            return self.nodes[i]
    def unite(self, i, j):
        i = self.find(i)
        j = self.find(j)
        if i == j:
            return
        if self.nodes[i] > self.nodes[j]: 
            i, j = j, i
        self.nodes[i] += self.nodes[j] 
        self.nodes[j] = i 
    
    def size(self, i): 
        i = self.find(i)
        return -self.nodes[i]

n, m = map(int, input().split())
ds = DisjointSets(n)
for _ in range(m):
    a, b = map(lambda x: int(x) - 1, input().split())
    ds.unite(a, b)

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

Solution (Python):
class UnionFind(object):
    def __init__(self, n):
        self.parent={i:i for i in range(1,n+1)}
        self.size={i:1 for i in range(1,n+1)}
    def find(self, a):
        if self.parent[a]!=a:
            self.parent[a]=self.find(self.parent[a])
        return self.parent[a]
    def getsize(self, a):
        return self.size[self.find(a)]
    def unite(self, a, b):
        a=self.find(a)
        b=self.find(b)
        if a==b:return
        if self.size[a]>self.size[b]:
            self.size[a]+=self.size[b]
            self.parent[b]=a
        else:
            self.size[b]+=self.size[a]
            self.parent[a]=b
    def isunited(self, a, b):
        return self.find(a)==self.find(b)

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

for _ in range(M):
    a, b = map(int, input().split())
    uf.unite(a, b)

for i in range(1, N+1):
    ans = max(ans, uf.getsize(i))

print(ans)

Solution (Python):


import sys
import math
from bisect import bisect_right as br
from bisect import bisect_left as bl
sys.setrecursionlimit(2147483647)
from heapq import heappush, heappop,heappushpop
from collections import defaultdict
from itertools import accumulate
from collections import Counter
from collections import deque
from operator import itemgetter
from itertools import permutations
mod = 10**9 + 7
inf = float('inf')
def I(): return int(sys.stdin.readline())
def LI(): return list(map(int,sys.stdin.readline().split()))

def root(x):
    if par[x] == x:
        return x
    par[x] = root(par[x])
    return par[x]

def union(x,y):
    x = root(x)
    y = root(y)
    if rank[x] < rank[y]:
        par[x] = y
    else:
        par[y] = x
        if rank[x] == rank[y]:
            rank[x] += 1

n, m = LI()
edges = [[] for _ in range(n)]
par = [i for i in range(n)]
rank = [0] * n
for _ in range(m):
    a, b = LI()
    if root(a-1) != root(b-1):
        union(a-1, b-1)

cnt = [0] * n
for i in range(n):
    cnt[root(i)] += 1
print(max(cnt))

Solution (Python):
n,m = 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 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())

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():
    num=uf.size(i)
    ans=max(ans,num)
print(ans)

Solution (Python):
import sys
input=sys.stdin.readline
def unite(x,y):
	rx=root(x);ry=root(y)
	if rank[rx]>rank[ry]:
		parent[ry]=rx
		size[rx]+=size[ry]
	else:
		parent[rx]=ry
		size[ry]+=size[rx]
		if rank[rx]==rank[ry]:
			rank[ry]+=1
def root(x):
	if x!=parent[x]:
		return root(parent[x])
	return x
def same(x,y):
	return root(x)==root(y)
n,m=map(int,input().split())
parent=list(range(n))
rank=[0]*n
size=[1]*n
for i in range(m):
	a,b=map(int,input().split())
	if same(a-1,b-1)==False:
		unite(a-1,b-1)

print(max(size))

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

from collections import Counter

class union_find():
    def __init__(self,n):
        self.n=n
        
        
        self.par=[-1 for i in range(n)]
        self.rank=[0]*(n)

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

    def union(self,x,y):
        x=self.find(x)
        y=self.find(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 same(self,x,y):
        return self.find(x) == self.find(y)
    
    def size(self,x):
      return -self.par[self.find(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.par) if x<0]
    
    def all_group_member(self):
      return {r:self.members(r) for r in self.roots()}
    
uf=union_find(n)
for _ in range(m):
  a,b=map(int,input().split())
  uf.union(a-1,b-1)
  
ans=0

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

Solution (Python):
from collections import*
class UnionFind():
  def __init__(self, n=10**6):
    self.n=n
    self.root=[-1]*(n+1)
    self.rnk=[0]*(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 
    elif(self.rnk[x] > self.rnk[y]):
      self.root[x]+=self.root[y]
      self.root[y]=x
    else:
      self.root[y]+=self.root[x]
      self.root[x]=y
      if(self.rnk[x]==self.rnk[y]):
        self.rnk[y]+=1
  def same(self, x, y):
    return self.find(x)==self.find(y)
  def count(self, x):
    return -self.root[self.find(x)]
n,m=map(int,input().split())
uf=UnionFind(n)
for _ in range(m):
  a,b=map(int,input().split())
  uf.unite(a,b)
a=list(Counter([uf.find(i) for i in range(1,n+1)]).values())
print(max(a))

Solution (Python):
from collections import defaultdict

N, M = map(int, input().split())
edges = defaultdict(set)

for _ in range(M):
    a, b = map(lambda x:int(x)-1, input().split())
    edges[a].add(b)
    edges[b].add(a)

ans = 0
visited = [False] * N

def dfs(i):
    stack = [i]
    ans = 0
    while stack:
        i = stack.pop()
        if visited[i]:
            continue
        ans += 1
        visited[i] = True
        for dest in edges[i]:
            stack.append(dest)
    return ans

for i in range(N):
    ans = max(ans, dfs(i))
print(ans)

Solution (Python):
import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time,copy,functools
from collections import deque

sys.setrecursionlimit(10**7)
inf = 10**20
mod = 10**9 + 7

DR = [1, -1, 0, 0]
DC = [0, 0, 1, -1]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x)-1 for x in sys.stdin.readline().split()]
def LF(): return [float(x) for x in sys.stdin.readline().split()]
def LS(): return sys.stdin.readline().split()
def I(): return int(sys.stdin.readline())
def F(): return float(sys.stdin.readline())
def S(): return input()
     
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())

def main():
    N, M = LI()
    u = UnionFind(N)
    for i in range(M):
        a, b = LI_()
        u.union(a, b)
    ans = 0
    for i in range(N):
        ans = max(ans, u.size(i))
    print(ans)


main()

Solution (Python):
from collections import defaultdict


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 same(self, x, y):
        return self.find(x) == self.find(y)


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

c = defaultdict(int)
for i in range(N):
    c[uf.find(i)] += 1

print(max(c.values()))

Solution (Python):
ma = lambda :map(int,input().split())
lma = lambda :list(map(int,input().split()))
tma = lambda :tuple(map(int,input().split()))
ni = lambda:int(input())
yn = lambda fl:print("Yes") if fl else print("No")
import collections
import math
import itertools
import heapq as hq
ceil = math.ceil
n,m = ma()
class unionfind():
    def __init__(self,n):
        self.par = list(range(n))
        self.size = [1]*n
        self.rank = [0]*n
        self.n = n
    def root(self,x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.root(self.par[x])
            return self.par[x]

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

    def unite(self,x,y):
        x = self.root(x)
        y = self.root(y)
        if x==y:return
        else:
            if self.rank[x] < self.rank[y]:
                 x,y = y,x
            if self.rank[x] == self.rank[y]:
                self.rank[x]+=1
            self.par[y] = x
            self.size[x] +=self.size[y]
    def get_size(self,x):
        x = self.root(x)
        return self.size[x]
    def parent_set(self):
        for x in range(self.n):
            self.root(x)
        s = set()
        for par in self.par:
            s.add(par)
        return s
uf = unionfind(n)
for i in range(m):
    a,b = ma()
    a-=1;b-=1
    uf.unite(a,b)
ans = 0
for i in range(n):
    ans=max(ans,uf.get_size(i))
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n)) 
        self.size = [1]*n 
 
    def root(self, x): 
        while self.parent[x] != x:
            self.parent[x] = self.parent[self.parent[x]]
            x = self.parent[x]
        return x 
 
    def merge(self, x, y): 
        x, y = self.root(x), self.root(y)
        if x == y: return False
        if self.size[x] < self.size[y]: x,y=y,x 
        self.size[x] += self.size[y] 
        self.parent[y] = x 
        return True
 
    def issame(self, x, y): 
        return self.root(x) == self.root(y)
        
    def getsize(self,x): 
        return self.size[self.root(x)]



import sys
readline = sys.stdin.readline
read = sys.stdin.read

n,m,*ab = map(int,read().split())

UF = UnionFind(n)

it = iter(ab)
for i,j in zip(it,it):
    UF.merge(i-1,j-1)

from collections import Counter
d = Counter(UF.root(i) for i in range(n))
print(max(d.values()))