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 collections import deque
N, M = map(int, input().split())
A = [set() for i in range(N+1)]
for i in range(M):
  a, b = map(int, input().split())
  A[a].add(b)
  A[b].add(a)
B = [0 for i in range(N+1)]
C = [0 for i in range(N+1)]
d = deque()
n = 1
for i in range(1, N+1):
  if B[i] != 0:
    continue
  d.append(i)
  C[n] += 1
  B[i] = n
  while len(d):
    e = d.pop()
    for k in A[e]:
      if B[k] == 0:
        d.append(k)
        C[n] += 1
        B[k] = 1
  n += 1
print(max(C))

Solution (Python):
'''
https://qiita.com/Kerzival/items/6923c2eb3b91be86f19f
'''

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

    
    def Count(self, x):
        return -self.root[self.Find_Root(x)]

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.Unite(A,B)

print(max([uf.Count(i) for i in range(N)]))

Solution (Python):
from collections import deque
import sys

N_MAX = 200000 + 5
INF = 10**9 + 7
sys.setrecursionlimit(N_MAX)
MOD = 10**9 + 7


ans = 0
group = 0




def bfs(u):

    V[u] = group
    cnt = 1  

    q = deque()
    q.append(u)
    while q:
        u = q.popleft()
        for v in E[u]:
            if V[v] == 0:  
                V[v] = group  
                cnt += 1  
                q.append(v)

    return cnt


N, M = map(int, sys.stdin.readline().rstrip().split())
V = [0] * N
E = [[] for _ in range(N)]
for i in range(M):
    a, b = map(int, sys.stdin.readline().rstrip().split())
    E[a - 1].append(b - 1)
    E[b - 1].append(a - 1)

for i in range(N):
    if V[i] == 0:
        group += 1
        ans = max(ans, bfs(i))


print(ans)

Solution (Python):
"""
def get_root(s):
    if s != root[s]:
        root[s] = get_root(root[s])
        return root[s]
    return s

def unite(s, t):
    root_s = get_root(s)
    root_t = get_root(t)
    if not root_s == root_t:
        if rank[s] == rank[t]:
            root[root_t] = root_s
            rank[root_s] += 1
        elif rank[s] > rank[t]:
            root[root_t] = root_s
        else:
            root[root_s] = root_t

def same(s, t):
    if get_root(s) == get_root(t):
        return True
    else:
        return False

n, m = map(int, input().split())
root = [i for i in range(n)]
rank = [1 for _ in range(n)]
size = [1 for _ in range(n)]
for _ in range(m):
    a, b = map(int, input().split())
    if not same(a - 1, b - 1):
        unite(a - 1, b - 1)
x = [0] * n
ans = 0
for i in range(n):
    j = get_root(i)
    x[j] += 1
    ans = max(ans, x[j])
print(ans)
"""

from collections import deque

def bfs(s):
    q = deque()
    q.append(s)
    visit[s] = 1
    cnt = 1
    while q:
        p = q.popleft()
        for j in G[p]:
            if visit[j] == 0:
                q.append(j)
                visit[j] = 1
                cnt += 1
    global ans
    ans = max(ans, cnt)
    return

n, m = map(int, input().split())
G = [[] for _ in range(n + 1)]
for _ in range(m):
    a, b = map(int, input().split())
    G[a].append(b)
    G[b].append(a)
visit = [0] * (n + 1)
ans = 0
for i in range(1, n + 1):
    if visit[i] == 0:
        bfs(i)
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, size):
        self.parent = [i for i in range(size)]
        self.size = [1]*size

    def find(self, x):
        if self.parent[x] == x:
            return x
        
        self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        
        if self.size[x] < self.size[y]:
            self.size[y] += self.size[x]
            self.parent[x] = y
        else:
            self.size[x] += self.size[y]
            self.parent[y] = x
    
    def same(self, x, y):
        return self.find(x) == self.find(y)
    
    def sizeofset(self, x):
        return self.size[self.find(x)]


if __name__ == "__main__":
    N, M = map(int,input().split())
    uf = UnionFind(N)
    for _ in range(M):
        a, b = map(int,input().split())
        uf.unite(a-1, b-1)
    print(max([uf.sizeofset(a) for a in range(N)]))

Solution (Python):
from heapq import heappush, heappop
import re
from collections import deque
import sys
import math
input = sys.stdin.readline


def int_raw():
    return int(input())


def ss_raw():
    return input().split()


def ints_raw():
    return tuple(map(int, ss_raw()))


DIV = 10**9+7


def mod_inv_prime(a, mod=DIV):
    return pow(a, mod-2, mod)


def mod_inv(a, b):
    r = a
    w = b
    u = 1
    v = 0
    while w != 0:
        t = r//w
        r -= t*w
        r, w = w, r
        u -= t*v
        u, v = v, u
    return (u % b+b) % b


def ncr(n, r, mod=DIV):
	r = min(r, n-r)
	ret = 1
	for i in range(1, r+1):
		ret = ret * (n-i+1) % mod
		ret = ret * mod_inv(i, mod) % mod
	return ret


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

    def find(self, x):
        if self.par[x] == x:
            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 self.rank[x] < self.rank[y]:
            self.par[x] = y
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
        mini = min(self.mini[x],self.mini[y])
        self.mini[x]=mini
        self.mini[y]=mini
    
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

def main():
    N ,M = ints_raw()
    uft = UnionFind(N)
    ABs = [ints_raw() for _ in range(M)]
    for ab in ABs:
        a,b = ab
        uft.union(a-1,b-1)
    pars = [0]*N
    for n in range(N):
        pars[uft.find(n)]+=1
    print(max(pars))
    
main()

Solution (Python):


import sys
from typing import Any, Callable, Deque, Dict, List, Mapping, Optional, Sequence, Set, Tuple, TypeVar, Union































def main():
    Num = Union[int, float]
    mod = 1000000007                
    inf = float('inf')              
    
    sys.setrecursionlimit(10**6)    
    def input():  return sys.stdin.readline().rstrip()
    def ii():     return int(input())
    def isp():    return input().split()
    def mi():     return map(int, input().split())
    def mi_0():   return map(lambda x: int(x)-1, input().split())
    def lmi():    return list(map(int, input().split()))
    def lmi_0():  return list(map(lambda x: int(x)-1, input().split()))
    def li():     return list(input())
    def debug(x): print(x, file=sys.stderr)
    
    
    class UnionFindTree:
        def __init__(self, num_of_elm: int):
            '''
            0 ... num_of_elem - 1 まで数字で表される (0-index) グループを管理する union find tree を作成する (O(n))
            '''
            self.n = num_of_elm
            self.table = [i for i in range(self.n)]    
            self.rank = [0] * self.n    
            self.group_size = [1] * self.n    
        
        def _find_set(self, x: int) -> int:
            '''
            x の属するグループ番号を O(α(n)) で求める
            '''
            parent = self.table[x]
            if x == parent:
                return x
            else:
                root = self._find_set(parent)
                
                self.table[x] = root
                return root
        
        def is_same(self, x: int, y: int) -> bool:
            '''
            x と y が同じグループに属するか O(α(n)) で判定する
            '''
            return self._find_set(x) == self._find_set(y)
    
        def union(self, x: int, y: int) -> bool:
            '''
            x と y の属するグループを O(α(n)) で統合する
            '''
            shallow_root = self._find_set(x)
            deep_root = self._find_set(y)
            if self.rank[shallow_root] > self.rank[deep_root]:
                shallow_root, deep_root = deep_root, shallow_root
            
            if shallow_root == deep_root:
                return False
            
            else:
                self.table[shallow_root] = deep_root
                self.group_size[deep_root] += self.group_size[shallow_root]
                
                if self.rank[shallow_root] == self.rank[deep_root]:
                    self.rank[deep_root] += 1
                return True
    
        def akin_num(self, x: int) -> int:
            '''
            x の属するグループのサイズを O(α(n)) で計算する
            '''
            x_root = self._find_set(x)
            return self.group_size[x_root]
    
        def __str__(self) -> str:
            return 'UFgroup(' + str([self._find_set(x) for x in self.table]) +')'


    n, m = mi()
    uf = UnionFindTree(n)
    cnt = 0
    for _ in range(m):
        a, b = mi_0()
        uf.union(a, b)

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




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

    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 {root: self.members(root) for root in self.roots()}



n, m = (int(x) for x in input().split())
if m == 0:
    print(1)
    exit()
AB = [tuple(int(x) - 1 for x in input().split()) for _ in range(m)]
uf = UnionFind(n)
for a, b in AB:
    uf.union(a, b)

ans = 0
for root in uf.roots():
    ans = max(ans, uf.size(root))
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())

from collections import defaultdict
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 = defaultdict(int)
for i in range(n):
    ans[uf.find(i)] += 1

print(max(ans.values()))

Solution (Python):
class Union():
    def __init__(self, N):
        self.Parent = []
        for i in range(N):
            self.Parent.append(-1)

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

    def size(self, A):
        return int(-1 * self.Parent[self.root(A)])

    def connect(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
        return True

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

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


print(ans)

Solution (Python):
import sys

input = sys.stdin.readline


class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n

    def root(self, x):
        if self.parent[x] == x:
            return x
        else:
            self.parent[x] = self.root(self.parent[x])
            return self.parent[x]

    def unite(self, x, y):
        root_x = self.root(x)
        root_y = self.root(y)
        if self.rank[x] > self.rank[y]:
            self.parent[root_y] = root_x
        elif self.rank[x] < self.rank[y]:
            self.parent[root_x] = root_y
        elif root_x != root_y:
            self.parent[root_y] = root_x
            self.rank[x] += 1
        pass


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

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

roots = [0] * n
for i in range(n):
    roots[uf.root(i)] += 1
ans = max(roots)

print(ans)

Solution (Python):
def main():
    n,m = map(int,input().split())
    g = {}
    for i in range(1,n+1):
        g[i] = []
    for i in range(m):
        a,b = map(int,input().split())
        g[a] += [b]
        g[b] += [a]
    G = [-1 for i in range(n)]
    c = 0
    for i in range(n):
        if G[i] !=-1:
            continue
        que = [i]
        G[i] = c
        while len(que) > 0:
            q = que.pop(0)
            for v in g[q+1]:
                if G[v-1]!=-1:
                    continue
                G[v-1] = c
                que.append(v-1)
        c += 1
    memb_cnt = [0 for i in range(c)]
    for i in range(n):
        memb_cnt[G[i]] += 1
    print(max(memb_cnt))

if __name__ == "__main__":
    main()

Solution (Python):
import sys
import math
from collections import defaultdict
from bisect import bisect_left, bisect_right

sys.setrecursionlimit(10**7)
def input():
    return sys.stdin.readline()[:-1]

mod = 10**9 + 7

def I(): return int(input())
def LI(): return list(map(int, input().split()))
def LIR(row,col):
    if row <= 0:
        return [[] for _ in range(col)]
    elif col == 1:
        return [I() for _ in range(row)]
    else:
        read_all = [LI() for _ in range(row)]
        return map(list, zip(*read_all))



N,M = LI()
A,B = LIR(M,2)

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

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

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

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

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

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

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

print(ans)

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

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


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):
import sys
stdin = sys.stdin
sys.setrecursionlimit(10**6)
ni = lambda: int(ns())
na = lambda: list(map(int, stdin.readline().split()))
nn = lambda: list(stdin.readline().split())
ns = lambda: stdin.readline().rstrip()

N = 3*10**5

*p, = range(N)
size = [1]*N
def root(x):
    if x == p[x]:
        return x
    p[x] = y = root(p[x])
    return y
def unite(x, y):
    px = root(x); py = root(y)
    if px == py:
        return 0
    sx = size[px]; sy = size[py]
    if sy < sx:
        p[py] = px
        size[px] += sy
    else:
        p[px] = py
        size[py] += sx
    return 1

n,m = na()
ans = 0

for i in range(m):
    a,b = na()
    unite(a,b)

print(max(size))

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

    def unite(self, x, y):
        x,y=self.find(x),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+1)
for i in range(M):
  a,b=map(int,input().split())
  uf.unite(a,b)
  
print(-min(uf.d))

Solution (Python):

class UnionFind():
    
    def __init__(self, n):
        self.par = [i for i in range(n)]  
        self.rank = [0 for _ in range(n)]  
        self.size = [1 for _ in range(n)]  

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

    
    def unite(self, x, y):
        
        x = self.find(x)
        y = self.find(y)
        if x == y:
            pass
        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 is_same(self, x, y):
        return self.find(x) == self.find(y)

    def get_size(self, x):
        return self.size[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-1,b-1)


for i in range(n):
    uf.find(i)

print(max(uf.size))

Solution (Python):

import sys
input = sys.stdin.readline
N,M = map(int,input().split())
F = [i for i in range(N)]

def find(n):
	if F[n] == n:
		return n
	ret = find(F[n])
	F[n] = ret
	return ret

def union(n,m):
	i, j = find(n), find(m)
	F[max(i,j)] = min(i,j)

for _ in range(M):
	A,B = map(int,input().split())
	A -= 1
	B -= 1
	union(A,B)

cnt = [0 for _ in range(N)]
for i in range(N):
	cnt[find(i)] += 1
print(max(cnt))

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


def main():
    from sys import setrecursionlimit, stdin, stderr
    from os import environ
    from collections import defaultdict, deque, Counter
    from math import ceil, floor
    from itertools import accumulate, combinations, combinations_with_replacement
    setrecursionlimit(10**6)
    dbg = (lambda *something: stderr.write("\033[92m{}\033[0m".format(str(something)+'\n'))) if 'TERM_PROGRAM' in environ else lambda *x: 0
    input = lambda: stdin.readline().rstrip()
    LMIIS = lambda: list(map(int,input().split()))
    II = lambda: int(input())
    P = 10**9+7
    INF = 10**18+10

    N,M = LMIIS()
    uf = UnionFind(N+1)
    for i in range(M):
        a,b = LMIIS()
        uf.union(a,b)
    max_size = 0
    roots = uf.roots()
    for r in roots:
        max_size = max(max_size,uf.size(r))
    print(max_size)

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

    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 = lambda: sys.stdin.readline().rstrip()

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

UF=UnionFind(n)

for i,j in a:
    i-=1
    j-=1
    UF.union(i,j)

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

Solution (Python):
inpl = lambda: list(map(int,input().split()))
class UnionFind:
    def __init__(self, N=None):
        if N is None or N < 1:
            self.parent = defaultdict(lambda: -1)
        else:
            self.parent = [-1]*int(N)

    def root_rec(self, n):
        if self.parent[n] < 0:
            return n
        else:
            m = self.root(self.parent[n])
            self.parent[n] = m
            return m

    def root(self, n):
        stack = []
        while n >= 0:
            stack.append(n)
            n = self.parent[n]
        m = stack.pop()
        while stack:
            self.parent[stack.pop()] = m
        return m

    def merge(self, m, n):
        rm = self.root(m)
        rn = self.root(n)
        if rm != rn:
            if -self.parent[rm] < -self.parent[rn]:
                rm, rn = rn, rm
            self.parent[rm] += self.parent[rn]
            self.parent[rn] = rm

    def size(self, n):
        return -self.parent[self.root(n)]
    
    def connected(self, m, n):
        return self.root(m) == self.root(n)

    def groups(self):
        if isinstance(self.parent,list):
            return list(filter(lambda i: self.parent[i]<0, range(len(self.parent))))
        else: 
            return list(filter(lambda i: self.parent[i]<0, self.parent.keys()))
 
    def groups_num(self):
        return len(self.groups())

    def elements(self):
        if isinstance(self.parent,list):
            return range(len(self.parent))
        else:
            return self.parent.keys()

N, M = inpl()
uf = UnionFind(N)
for _ in range(M):
    A, B = inpl()
    uf.merge(A-1, B-1)

ans = max(uf.size(g) for g in uf.groups())
print(ans)

Solution (Python):
class DisjointSets:
    def __init__(self,n):
        self.parent = [i for i in range(n)]
        self.siz = [1]*n
        self.grp = n

    def root(self,x):
        if x != self.parent[x]: 
            self.parent[x] = self.root(self.parent[x])
        return self.parent[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
        if self.siz[x] < self.siz[y]: 
            x,y = y,x
        self.parent[y] = x
        self.siz[x] += self.siz[y]
        self.grp -= 1

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

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

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

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

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

    res = 0
    for i in range(N):
        s = u.size(i)
        if res < s:
            res = s

    print(res)


if __name__ == "__main__":
    main()

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


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


par = [-1]*(N+1)

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

ans = 1
for i in range(1,N+1):
    ans = max(ans,size(i))

print(ans)

Solution (Python):
import sys
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 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 main():
    input = sys.stdin.readline
    n, m = map(int, input().split())
    uf = UnionFind(n)
    for _ in range(m):
        a, b = map(lambda x: int(x) - 1, input().split())
        uf.union(a, b)
    ans = max(-uf.parents[uf.find(x)] for x in uf.roots())
    print(ans)


if __name__ == '__main__':
    main()