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):
from sys import stdin
import collections
def ip(): return [int(i) for i in stdin.readline().split()]
def sp(): return [str(i) for i in stdin.readline().split()]









def find(d,x):
    root = x
    while root != d[root]:
        root = d[root]

    while x != root:
        nxt = d[x]
        d[x] = root
        x = nxt
    return d,root


def merge(d,s,x,y):
    d,x = find(d,x)
    d,y = find(d,y)
    if x == y: return d,s
    if s[x] > s[y]:
        s[x] += s[y]
        d[y] = d[x]
    else:
        s[y] += s[x]
        d[x] = d[y]
    return d,s


n,m = ip()
d = {i+1: i+1 for i in range(n)}
s = {i+1: 1 for i in range(n)}
seen = set()
for _ in range(m):
    
    x,y = ip()
    if (x,y) in seen or (y,x) in seen: continue
    seen.add((x,y))
    seen.add((y,x))
    d,s = merge(d,s,x,y)
ans = 0
for i in s:
    ans = max(ans, s[i])
print(ans)

Solution (Python):

import zlib
import base64
import subprocess


exe_bin = "c%1E9eRLDol^=Z=8w`>lCNW<@p(ceSR;(bvB4)8{3C2V?Ua*OiKqg`&V>Plwq!HNJmT)jm859v8&Th-eZduap>85mhmQA;Na_H`2aDa5TJta*~!ZvBvrwy$XH^E&Jz5;0Pee<3?GuAZeZvW)@*!SJvyZ65P?!5PA=FRo9f

open("./kyomu", 'wb').write(zlib.decompress(base64.b85decode(exe_bin)))
subprocess.run(["chmod +x ./kyomu"], shell=True)
subprocess.run(["./kyomu"], shell=True)

Solution (Python):
import sys
if sys.argv[-1] == 'ONLINE_JUDGE':
    import os, zlib, base64
    open('solve.pyx', 'wb').write(zlib.decompress(base64.b85decode("c$|e)+isjN5PkPoj1*-9SuS1WrHVp+Bt^(JW@FVDWSfWd>pKQYutPVz80K>3oEbBB&`RqjCzX8$MfG)}S5fivncVF?Qgb!6qG_eERrx;jqU3{i!aAy5S*U?iRVvBK@x
    os.system('cythonize -i -3 -b solve.pyx')
import solve

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())
f_uf = UnionFind(N)
for _ in range(M):
  a, b = map(int, input().split())
  f_uf.union(a-1, b-1)
answer = 1
for i in range(N):
  answer = max(answer, f_uf.size(i))
print(answer)

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 i in range(m)]

ans=0
u=UnionFind(n)
for a,b in ab:
    u.union(a-1,b-1)

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

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

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.root = [-1]*(n+1)
        self.rank = [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.rank[x] > self.rank[y]:
            self.root[x] += self.root[y]
            self.root[y] = x

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            if self.rank[x] == self.rank[y]:
                self.rank[y] += 1

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


    def count(self, x):
        return (-1)*self.root[self.find(x)]

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

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

ans = 0

for i in range(n):
    ans = max(ans, uf.count(i))

print(ans)

Solution (Python):

import base64
import subprocess


exe_bin = "e??420s

open("./kyomu", 'wb').write(base64.b85decode(exe_bin))
subprocess.run(["chmod +x ./kyomu"], shell=True)
subprocess.run(["./kyomu"], shell=True)

Solution (Python):
from collections import deque

n, m = map(int, input().split())
ab = [list(map(int, input().split())) for _ in range(m)]

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

for a, b in ab:
    t[a].append(b)
    t[b].append(a)

ans = 1
frag = [True]*(n+1)
d = deque()

for i in range(1, n+1):
    if not frag[i]:
        continue
    d.append(i)
    l = []
    while d:
        num = d.popleft()
        for j in t[num]:
            if not frag[j]:
                continue
            d.append(j)
            l.append(j)
            frag[j] = False
    ans = max(ans, len(set(l)))

print(ans)

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


def find(x):
    while par[x] != x:
        par[x] = par[par[x]]
        x = par[x]
    return x


def union(x, y):
    x1 = find(x)
    y1 = find(y)
    if x1 != y1:
        par[x1] = y1


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

s = [0 for i in range(n + 1)]

for k in range(n):
    s[find(k)] += 1


print(max(s))

Solution (Python):
mycode = r'''





ctypedef long long LL
from libc.stdio cimport scanf, printf
from libcpp.vector cimport vector
ctypedef vector[LL] vec


cdef class UnionFind:
    cdef:
        LL N,n_groups
        vec parent

    def __init__(self, LL N):
        self.N = N  
        self.n_groups = N  
        
        self.parent = vec(N,-1)  

    cdef LL root(self, LL A):
        
        
        if (self.parent[A] < 0):
            return A
        self.parent[A] = self.root(self.parent[A])  
        return self.parent[A]

    cdef LL size(self, LL A):
        
        return -self.parent[self.root(A)]

    cdef bint unite(self,LL A,LL B):
        
        
        A = self.root(A)
        B = self.root(B)

        
        if (A == B):
            return False

        
        if (self.size(A) < self.size(B)):
            A, B = B, A

        
        self.parent[A] += self.parent[B]  
        self.parent[B] = A  
        self.n_groups -= 1

        return True

    cdef bint is_in_same(self,LL A,LL B):
        return self.root(A) == self.root(B)


cdef LL N,M,_
scanf('%lld %lld',&N, &M)

cdef UnionFind uf = UnionFind(N)
cdef LL a,b
for _ in range(M):
    scanf('%lld %lld',&a, &b)
    uf.unite(a-1, b-1)

print(-min(uf.parent))
'''

import sys
import os
if sys.argv[-1] == 'ONLINE_JUDGE':  
    with open('mycode.pyx', 'w') as f:
        f.write(mycode)
    os.system('cythonize -i -3 -b mycode.pyx')

import mycode

Solution (Python):
mycode = r'''





ctypedef long long LL
from libcpp.vector cimport vector
ctypedef vector[LL] vec


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

def ints(): return map(int,readline().split())


cdef class UnionFind:
    cdef:
        public LL N,n_groups
        public vec parent

    def __init__(self, LL N):
        self.N = N  
        self.n_groups = N  
        
        self.parent = vec(N,-1)  

    cdef LL root(self, LL A):
        
        
        if (self.parent[A] < 0):
            return A
        self.parent[A] = self.root(self.parent[A])  
        return self.parent[A]

    cdef LL size(self, LL A):
        
        return -self.parent[self.root(A)]

    cdef bint unite(self,LL A,LL B):
        
        
        A = self.root(A)
        B = self.root(B)

        
        if (A == B):
            return False

        
        if (self.size(A) < self.size(B)):
            A, B = B, A

        
        self.parent[A] += self.parent[B]  
        self.parent[B] = A  
        self.n_groups -= 1

        return True

    cdef bint is_in_same(self,LL A,LL B):
        return self.root(A) == self.root(B)


cdef LL N,M,_



N, M = ints()
cdef UnionFind uf = UnionFind(N)
cdef LL a,b
for _ in range(M):
    a,b=ints()
    uf.unite(a-1, b-1)

print(-min(uf.parent))

'''

import sys
import os
if sys.argv[-1] == 'ONLINE_JUDGE':  
    with open('mycode.pyx', 'w') as f:
        f.write(mycode)
    os.system('cythonize -i -3 -b mycode.pyx')

import mycode

Solution (Python):
mycode = r'''




ctypedef long long LL

import numpy as np
from functools import partial
array=partial(np.array, dtype=np.int64)
zeros=partial(np.zeros, dtype=np.int64)
full=partial(np.full, dtype=np.int64)

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

cdef ints(): return np.fromstring(readline(), sep=' ', dtype=np.int64)

cdef read_matrix(LL H,LL W):
    
    lines=[]
    cdef LL _
    for _ in range(H): 
        lines.append(read())
    lines=' '.join(lines) 
    return np.fromstring(lines, sep=' ',dtype=np.int64).reshape(H,W)

cdef class UnionFind:
    cdef:
        public LL N,n_groups
        public LL[::1] parent

    def __init__(self, LL N):
        self.N = N  
        self.n_groups = N  
        
        self.parent = full(N,-1)  

    cdef LL root(self, LL A):
        
        
        if (self.parent[A] < 0):
            return A
        self.parent[A] = self.root(self.parent[A])  
        return self.parent[A]

    cdef LL size(self, LL A):
        
        return -self.parent[self.root(A)]

    cdef bint unite(self,LL A,LL B):
        
        
        A = self.root(A)
        B = self.root(B)

        
        if (A == B):
            return False

        
        if (self.size(A) < self.size(B)):
            A, B = B, A

        
        self.parent[A] += self.parent[B]  
        self.parent[B] = A  
        self.n_groups -= 1

        return True

    cdef bint is_in_same(self,LL A,LL B):
        return self.root(A) == self.root(B)


cdef LL N,M

N, M = ints()
AB=read_matrix(M,2)-1
cdef UnionFind uf = UnionFind(N)
cdef LL a,b
for a,b in AB:
    uf.unite(a, b)

print(-np.min(uf.parent))
'''

import sys
import os
if sys.argv[-1] == 'ONLINE_JUDGE':  
    with open('mycode.pyx', 'w') as f:
        f.write(mycode)
    os.system('cythonize -i -3 -b mycode.pyx')

import mycode

Solution (Python):
import sys
sys.setrecursionlimit(1 << 25)
readline = sys.stdin.buffer.readline
read = sys.stdin.readline  
ra = range
enu = enumerate


def exit(*argv, **kwarg):
    print(*argv, **kwarg)
    sys.exit()


def mina(*argv, sub=1): return list(map(lambda x: x - sub, argv))



def a_int(): return int(readline())


def ints(): return list(map(int, readline().split()))


def read_col(H):
    '''H is number of rows
    A列、B列が与えられるようなとき
    ex1)A,B=read_col(H)    ex2) A,=read_col(H) 
    ret = []
    for _ in range(H):
        ret.append(list(map(int, readline().split())))
    return tuple(map(list, zip(*ret)))


def read_tuple(H):
    '''H is number of rows'''
    ret = []
    for _ in range(H):
        ret.append(tuple(map(int, readline().split())))
    return ret


def read_matrix(H):
    '''H is number of rows'''
    ret = []
    for _ in range(H):
        ret.append(list(map(int, readline().split())))
    return ret
    


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

    def root(self, A):
        
        
        if (self.parent[A] < 0):
            return A
        self.parent[A] = self.root(self.parent[A])  
        return self.parent[A]

    def size(self, A):
        
        return -self.parent[self.root(A)]

    def unite(self, A, B):
        
        
        A = self.root(A)
        B = self.root(B)

        
        if (A == B):
            return False

        
        if (self.size(A) < self.size(B)):
            A, B = B, A

        
        self.parent[A] += self.parent[B]  
        self.parent[B] = A  
        self.n_groups -= 1

        return True

    def is_in_same(self, A, B):
        return self.root(A) == self.root(B)


MOD = 10**9 + 7
INF = 2**31  

from collections import defaultdict, Counter, deque
from operator import itemgetter, xor, add
from itertools import product, permutations, combinations
from bisect import bisect_left, bisect_right  
from functools import reduce
from math import gcd


def lcm(a, b):
    
    g = gcd(a, b)
    return a // g * b


N, M = ints()
uf = UnionFind(N)
for _ in range(M):
    a, b = mina(*ints())
    uf.unite(a, b)





print(-min(uf.parent))

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)]

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

ans=0

for i in range(N):
    if uf.size(i) > ans:
        ans=uf.size(i)
        
print(ans)

Solution (Python):
class UFTree:
    def __init__(self, N):
        self.nodes = [Node(i) for i in range(N)]
        self.N = N

    def find_max_child_num(self):
        result = 0
        for i in range(self.N):
            result = max(result, self.nodes[i].child_num)
        return result

class Node:
    def __init__(self, ID):
        self.ID = ID
        self.parent = None
        self.child_num = 0
        self.rank = 1

    def get_root(self):
        if self.parent is None:
            return self
        
        return self.parent.get_root()

    def concat(self, another):
        sr = self.get_root()
        ar = another.get_root()

        
        if sr.ID == ar.ID:
            return

        if sr.rank > ar.rank:
            parent, child = sr, ar
        else:
            parent, child = ar, sr

        parent.child_num += child.child_num + 1
        parent.rank = max(parent.rank, child.rank + 1)
        child.parent = parent

N, M = map(int, input().split())
tree = UFTree(N)

AB = []
for i in range(M):
    l = list(map(int, input().split()))
    AB.append(l)

for i in range(M):
    a, b = AB[i][0], AB[i][1]
    a -= 1;
    b -= 1;

    tree.nodes[a].concat(tree.nodes[b])

print(tree.find_max_child_num() + 1)

Solution (Python):
class UFTree:
    def __init__(self, N):
        self.nodes = [Node(i) for i in range(N)]
        self.N = N

    def find_max_child_num(self):
        result = 0
        for i in range(self.N):
            result = max(result, self.nodes[i].child_num)
        return result

class Node:
    def __init__(self, ID):
        self.ID = ID
        self.parent = None
        self.child_num = 0
        self.rank = 1

    def get_root(self):
        if self.parent is None:
            return self
        
        return self.parent.get_root()

    def concat(self, another):
        sr = self.get_root()
        ar = another.get_root()

        
        if sr.ID == ar.ID:
            return

        if sr.rank > ar.rank:
            parent, child = sr, ar
        else:
            parent, child = ar, sr

        parent.child_num += child.child_num + 1
        parent.rank = max(parent.rank, child.rank + 1)
        child.parent = parent

N, M = map(int, input().split())
tree = UFTree(N)

AB = []
for i in range(M):
    l = list(map(int, input().split()))
    AB.append(l)

for i in range(M):
    a, b = AB[i][0], AB[i][1]
    a -= 1;
    b -= 1;

    tree.nodes[a].concat(tree.nodes[b])

print(tree.find_max_child_num() + 1)

Solution (Python):
class UFTree:
    def __init__(self, N):
        self.nodes = [Node(i) for i in range(N)]
        self.N = N

    def find_max_child_num(self):
        result = 0
        for i in range(self.N):
            result = max(result, self.nodes[i].child_num)
        return result

class Node:
    def __init__(self, ID):
        self.ID = ID
        self.parent = None
        self.child_num = 0
        self.rank = 1

    def get_root(self):
        if self.parent is None:
            return self
        
        return self.parent.get_root()

    def is_in_same_tree(self, another):
        return self.get_root().ID == another.get_root().ID

    def concat(self, another):
        if self.is_in_same_tree(another):
            return

        sr = self.get_root()
        ar = another.get_root()

        if sr.rank > ar.rank:
            parent, child = sr, ar
        else:
            parent, child = ar, sr

        parent.child_num += child.child_num + 1
        parent.rank = max(parent.rank, child.rank + 1)
        child.parent = parent

N, M = map(int, input().split())
tree = UFTree(N)

AB = []
for i in range(M):
    l = list(map(int, input().split()))
    AB.append(l)

for i in range(M):
    a, b = AB[i][0], AB[i][1]
    a -= 1;
    b -= 1;

    tree.nodes[a].concat(tree.nodes[b])









print(tree.find_max_child_num() + 1)

Solution (Python):


class UnionFind:
    def __init__(self, size):
        self.rank = [0 for i in range(size)]
        self.parent = [-1 for i in range(size)]
        self.children = [[i] for i in range(size)]
    
    def Find(self, x):
        parent = self.parent[x]
        while parent >= 0:
            x = parent
            parent = self.parent[x]
        return x
    
    def Union(self, x, y):
        root_x = self.Find(x)
        root_y = self.Find(y)
        if root_x == root_y:
            return
        else:
            if self.rank[root_x] >= self.rank[root_y]:
                self.parent[root_x] += self.parent[root_y]
                self.parent[root_y] = root_x
                self.rank[root_x] = max(self.rank[root_y] + 1, self.rank[root_x])
                self.children[root_x] += self.children[root_y]
            else:
                self.parent[root_y] += self.parent[root_x]
                self.parent[root_x] = root_y
                self.rank[root_y] = max(self.rank[root_x] + 1, self.rank[root_y])
                self.children[root_y] += self.children[root_x]
    def Same(self, x, y):
        return self.Find(x) == self.Find(y)
    def FindRootAndSizeAndChildren(self):
        return [(idx, -val, self.children[idx]) for idx, val in enumerate(self.parent) if val<0 ]
    def print_lists(self):
        print(self.rank)
        print(self.parent)
        print()


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

max_size = 0
for idx, size, children in unionfind.FindRootAndSizeAndChildren():
    if size > max_size:
        max_size = size
print(max_size)

Solution (Python):
class UnionFind:
    def __init__(self,n):
        self.par = {i:i for i in range(1,n+1)}
        self.rank = {i:0 for i in range(1,n+1)}
        self.size = {i:1 for i in range(1,n+1)}

    def find(self,x):
        if x != self.par[x]:
            self.par[x] = self.find(self.par[x])
        return self.par[x]

    def union(self,x,y):
        px,py = self.find(x),self.find(y)
        res = 0
        if px != py:
            if self.rank[px] < self.rank[py]:
                self.par[px] = py
                self.size[py] += self.size[px]
                res = self.size[py]
            else:
                self.par[py] = px
                self.size[px] += self.size[py]
                if self.rank[px] == self.rank[py]:
                    self.rank[px] += 1
                res = self.size[px]
        return res

n,m = map(int,input().split())
ans = 1
uf = UnionFind(n)
for _ in range(m):
    a,b = map(int,input().split())
    ans = max(ans,uf.union(a,b))
print(ans)

Solution (Python):
def find(x):
  if par[x] < 0:
    return x
  else:
    par[x] = find(par[x])
    return par[x]

def unite(x,y):
  x,y=find(x),find(y)
  if x!=y:
    if x>y:
        x,y=y,x
    par[x]+=par[y] 
    par[y]=x 

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

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

par = [-1] * 200005


def main():
  n, m = map(int, input().split())
  for i in range(m):
    a, b = map(int, input().split())
    unite(a-1, b-1)
  print(abs(min(par)))
  
if __name__ == "__main__":
  main()

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

def find(x):

    while par[x] != x:
        par[x] = par[par[x]]
        x = par[x]

    return x


def union(x, y):
    x1 = find(x)
    y1 = find(y)
    if x1 != y1:
        par[x1] = y1


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

s = [0 for i in range(n + 1)]

for k in range(n):
    s[find(k)] += 1


print(max(s))

Solution (Python):

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

def unite(x, y):
    x = root(x)
    y = root(y)
    if x != y:
        if r[x] > r[y]:
            x,y = y,x
        r[x] += r[y]
        r[y] = x

def size(x):
    return -r[root(x)]
 
n,m = map(int,input().split())
r = [-1] * n 
for i in range(m):
    a,b = map(int, input().split())
    a -= 1
    b -= 1
    unite(a,b)
ans = 0
for i in range(n):
    ans = max(ans,size(i))
print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(10**6)
N,M=map(int,input().split())

class union_find():

    def __init__(self,n):
        self.n = n
        self.root = [-1]*n
        self.rank = [0]*n

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

    def unite(self,x,y):
        x = self.find_root(x)
        y = self.find_root(y)
        if x==y:
            return
        elif self.rank[x]>self.rank[y]:
            self.root[x]+=self.root[y]
            self.root[y]=x
        else:
            self.root[y]+=self.root[x]
            self.root[x]=y
            if self.rank[x]==self.rank[y]:
                self.rank[y]+=1

    def same(self,x,y):
        x = self.find_root(x)
        y = self.find_root(y)
        if x==y:
            return True
        else:
            return False

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

G = union_find(N)
for i in range(M):
    a,b=map(int,input().split())
    a-=1
    b-=1
    G.unite(a,b)

ans = 0
for i in range(N):
    tmp = G.count(i)
    ans = max(ans,tmp)

print(ans)

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

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

root = [-1] * N


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


def unite(x, y):
    x = r(x)
    y = r(y)
    if x == y:
        return
    
    root[x] += root[y]
    root[y] = x


def size(x):
    return -r(x)


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

max_size = -min(root)
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 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 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 group_members(self):
        return [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+1)
for _ in range(m):
    x, y = map(int, input().split())
    uf.unite(x, y)

ans = 0
for i in range(n+1):
    if ans < uf.size(i):
        ans = uf.size(i)
print(ans)

Solution (Python):
import sys


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())
info = [tuple(map(int, s.split())) for s in sys.stdin.readlines()]


uf = UnionFind(N)
for a, b in info:
    
    a -= 1; b -= 1
    uf.union(a, b)

ans = min(uf.parents)

print(-ans)

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


root = list(range(n + 1))




cnt = [1] * (n + 1)


def find(i):
    if i == root[i]:
        return i
    root[i] = find(root[i])
    return root[i]

def union(u, v):
    fu, fv = find(u), find(v)
    if fu == fv:
        return
    root[max(fu, fv)] = min(fu, fv)
    cnt[min(fu, fv)] += cnt[max(fu, fv)]



for i in range(m):
    u, v = map(int, input().split())
    union(u, v)




print(max(cnt))

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


root = list(range(n + 1))




cnt = [1] * (n + 1)


def find(i):
    if i == root[i]:
        return i
    root[i] = find(root[i])
    return root[i]

def union(u, v):
    fu, fv = find(u), find(v)
    if fu == fv:
        return
    cnt[min(fu, fv)] += cnt[max(fu, fv)]
    root[max(fu, fv)] = min(fu, fv)



for i in range(m):
    u, v = map(int, input().split())
    union(u, v)




print(max(cnt))

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

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

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

        self.parents[x] += self.parents[y]
        self.parents[y] = x
        return -self.parents[self.find(x)]

def main():
    N, M = map(int, input().split())
    uf = UnionFind(N+1)
    ans = 1
    if M == 0:
        print(ans)
        return

    for i in range(M):
        x, y = map(int, input().split())
        ans = max(uf.union(x,y), ans)
    print(ans)

if __name__ == '__main__':
    main()

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)]


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

uf = UnionFind(n+1)

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

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

print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(10**6)
N,M = map(int,input().split())

class Union_Find():

    def __init__(self,n):
        self.n = n
        self.root = [-1]*(n+1)
        self.rank = [0]*(n+1)

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

    def unite(self,x,y):
        x = self.find_root(x)
        y = self.find_root(y)

        if x==y:
            return
        elif self.rank[x]>self.rank[y]:
            self.root[x]+=self.root[y]
            self.root[y]=x
        else:
            self.root[y]+=self.root[x]
            self.root[x]=y

            if self.rank[x]==self.rank[y]:
                self.rank[y]+=1

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

    def cnt(self,x):
        return -self.root[self.find_root(x)]

G=Union_Find(N)
ans=0
for i in range(M):
    a,b=map(int,input().split())
    G.unite(a,b)

for i in range(1,N+1):
    ans = max(ans,G.cnt(i))
print(ans)