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

Solution (Python):
class DisjointSet:
    def __init__(self,size):
        self.rank = [None]*size
        self.size = [None]*size
        self.p = [None]*size
        for i in range(size):
            self.make_set(i)
        return
    
    def make_set(self,x):
        self.p[x] = x
        self.rank[x] = 0
        self.size[x] = 1
        return
    
    def same(self,x,y):
        return self.find_set(x) == self.find_set(y)
        
    def unite(self,x,y):
        self.link(self.find_set(x),self.find_set(y))
        return
    
    def link(self,x,y):
        if self.rank[x]>self.rank[y]:
            self.p[y] = x
            self.size[x] += self.size[y]
        else:
            self.p[x] = y
            self.size[y] += self.size[x]
            if self.rank[x]==self.rank[y]:
                self.rank[y] += 1
                
    def find_set(self,x):
        if x != self.p[x]:
            self.p[x] = self.find_set(self.p[x])
        return self.p[x]
    

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

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

print(max(djs.size))

Solution (Python):
from collections import Counter
N, M = map(int,input().split())
par = []
rank = [0] * N
for i in range(N): par.append(i)
def find(x):
    if par[x] == x: return x
    else:
         par[x] = find(par[x])
         return par[x]
def unite(x,y):
    x = find(x)
    y = find(y)
    if x == y: return 0
    if rank[x] < rank[y]: par[x] = y
    else:
        par[y] = x
        if rank[x] == rank[y]: rank[x] += 1

for i in range(M):
    A, B = map(int,input().split())
    A -= 1
    B -= 1
    unite(A,B)
for i in range(N):find(i)    
print(Counter(par).most_common()[0][1])

Solution (Python):









import os
import sys
sys.setrecursionlimit(900000)


from collections import Counter


def dfs(u, color, path, n, d):
    color[u] = d
    for v in path[u]:
        if color[v] == -1:
            dfs(v, color, path, n, d)



def main():
    n, m = map(int, input().split())
    path = [[] for _ in range(n+1)]
    for _ in range(m):
        a, b = map(int, input().split())
        path[a].append(b)
        path[b].append(a)
    color = [-1]*(n+1)
    d = 0
    for i in range(1, n+1):
        if color[i] == -1:
            dfs(i, color, path, n, d)
            d += 1
    color = color[1:]
    color_cnt = Counter(color).values()
    print(max(color_cnt))



if __name__ == "__main__":
    main()

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

def dfs(G, v, p):
    seen[v] = True
    for nv in G[v]:
        if nv == p: continue
        if seen[nv]: continue
        dfs(G, nv, v)
    
    for c in G[v]:
        if c != p: continue
        sz[p] += (sz[v]+1)

n, m = map(int, input().split())
ab = []
for _ in range(m):
    a, b = map(int, input().split())
    a, b = a-1, b-1
    if a > b:
        a, b = b, a
    ab.append((a, b))
ab = set(ab)

G = [[] for _ in range(n)]
for a, b in ab:
    G[a].append(b)
    G[b].append(a)

seen = [False]*n
sz = [0]*n
for i in range(n):
    if not seen[i]:
        dfs(G, i, -1)

print(max(sz)+1)

Solution (Python):
N,M=list(map(int,input().split()))
l=[[] for i in range(N)]
l_c=[0 for i in range(N)]
for i in range(M):
   a,b=list(map(int,input().split()))
   a-=1;b-=1
   l[a].append(b)
   l[b].append(a)
from collections import deque
def search(start):
   cnt=1
   que=deque([start])
   l_c[start]=1
   while que:
      A=que.popleft()
      for i in l[A]:
         if l_c[i]==0:
            cnt+=1
            l_c[i]=1
            que.append(i)
   return cnt
ans=0
for i in range(N):
   if l_c[i] ==0:
      ans=max(ans,search(i))
print(ans)

Solution (Python):
import numpy as np
from scipy.sparse.csgraph import connected_components
from scipy.sparse import csr_matrix
import collections

N, M = map(int, input().split())
edge = np.array([input().split() for _ in range(M)], dtype=np.int64).T

if M == 0:
    print(1)
else:
    tmp = np.ones(M, dtype=np.int64).T
    graph = csr_matrix((tmp, (edge[:] - 1)), (N, N))

    n, labels = connected_components(graph)

    c = collections.Counter(labels)

    print(max(c.values()))

Solution (Python):
from collections import Counter 

class UnionFind(object):
    def __init__(self, n=1):
        self.par = [i for i in range(n)]
        self.rank = [0 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 union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            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

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

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

for _ in range(M):
    x, y = map(int, input().split())
    uf1.union(x-1,y-1)

for i in range(N):
    uf1.find(i) 
c = list(Counter(uf1.par).values())
print(max(c))

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

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

arr = []
for i in range(n):
    if par[i]<0:
        arr.append(-par[i])
        
arr=sorted(arr)
ans=0
div=0
k=len(arr)
for j in range(k):
    if j!=k-1:
        if arr[j]-div!=0:
            ans+=arr[j]-div
            div+=arr[j]-div
    elif j==k-1:
        if arr[j]-div!=0:
            ans+=arr[j]-div


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

def resolve():
    N, M = list(map(int, input().split()))
    uf = UnionFind(N)
    for i in range(M):
        a, b = list(map(int, input().split()))
        uf.union(a-1, b-1)
    maxnum = 0
    for v in uf.parents:
        if v < 0:
            maxnum = max(maxnum, -v)
    print(maxnum)

if '__main__' == __name__:
    resolve()

Solution (Python):
from collections import deque

class Graph():
    def __init__(self):
        """ ノードのつながりを辞書型で表現する """
        self.adjacency_dict = {}

    def add_vertex(self, v):
        """ ノードを追加する """
        self.adjacency_dict[v] = []
    def add_edge(self, v1, v2):
        """ ノード同士をつなぐ。"""
        
        self.adjacency_dict[v1].append(v2)
        self.adjacency_dict[v2].append(v1)
    def next_vertices(self, v):
        """ 隣接したノードを返す """
        return self.adjacency_dict[v]

def bfs(start):
    visited[start] = True
    q = deque()
    q.append(start)

    group_size = 1
    while q:
        v_now = q.popleft()
        for v_next in graph.next_vertices(v_now):
            if visited[v_next] == False:
                visited[v_next] = True
                q.append(v_next)
                group_size += 1

    return group_size
    

N, M = map(int, input().split())
AB = [list(map(int, input().split())) for _ in range(M)]

graph = Graph()
for i in range(1, N+1):
    graph.add_vertex(i)
for v1, v2 in AB:
    graph.add_edge(v1, v2)

visited = [False] * (N+1)

max_group_size = 1
for i in range(1, N+1):
    if visited[i] == False:
        group_size = bfs(i)
        max_group_size = max(max_group_size, group_size)
    
print(max_group_size)

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


input = sys.stdin.buffer.readline
N, M = map(int, input().split())

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



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

Solution (Python):
from collections import Counter
N,M = (int(T) for T in input().split())
def FindParent(X):
    if Parent[X]==X:
        return X
    else:
        Parent[X] = FindParent(Parent[X])
        return Parent[X]

def IsSameParent(X,Y):
    return FindParent(X)==FindParent(Y)

def UniteParent(X,Y):
    X = FindParent(X)
    Y = FindParent(Y)
    if X==Y:
        return 0
    if Rank[X]<Rank[Y]:
        Parent[X] = Y
    else:
        Parent[Y] = X
        if Rank[X]==Rank[Y]:
            Rank[X] += 1
Parent = [I for I in range(N+1)]
Rank = [0]*(N+1)
for TM in range(0,M):
    A,B = (int(T) for T in input().split())
    UniteParent(A,B)
for TN in range(1,N+1):
    FindParent(TN)
print(Counter(Parent[1:]).most_common()[0][1])

Solution (Python):

import sys
sys.setrecursionlimit(1000000)
N,M = map(int, input().split())

parent_dict = dict() 


def add_connect(A,B):
    A_parent = get_parent(A)
    B_parent = get_parent(B)
    
    if A_parent != B_parent:
        parent_dict[B_parent] = A_parent


def judge_connection(A,B):
    A_parent = get_parent(A) 
    B_parent = get_parent(B)
    
    if A_parent != B_parent:
        return False
    else:
        return True


def get_parent(child):
    if child not in parent_dict: 
        parent_dict[child] = child
    
    parent = parent_dict[child]
    
    if parent == child: 
        return parent
    else: 
        parent_dict[child] = get_parent(parent) 
        return parent_dict[child]




for i in range(M):
    A,B = map(int, input().split())
    add_connect(A,B)

for i in range(1,N+1):
    get_parent(i)




child_dict = dict() 

for i in range(1,N+1):
    if parent_dict[i] not in child_dict:
        child_dict[parent_dict[i]] = set()
    child_dict[parent_dict[i]].add(i)


ans = 1
for parent in child_dict:
    if len(child_dict[parent]) > ans:
        ans = len(child_dict[parent])

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 solve():
    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)
    rt_l = UF.roots()
    ans = 0
    for _rt in rt_l:
        _len = UF.size(_rt)
        if ans < _len:
            ans = _len

    print(ans)


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())
uf = UnionFind(n)
for i in range(m):
    a, b = map(int, input().split())
    uf.union(a-1, b-1)
print(max([uf.size(i)for i in range(n)]))

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

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

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

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

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

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

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

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

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

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

for _ in range(M):
    a,b=[int(e)-1 for e in input().split()]
    uf.union(a,b)
ans=max([uf.size(i) for i in range(N)])
print(ans)

Solution (Python):
import sys
from collections import Counter

class UnionFindTree:
    def __init__(self, n: int) -> None:
        self.par = list(range(n))
        self.rank = [0] * n

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

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

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


def resolve(in_):
    N, M = map(int, next(in_).split())
    AB = tuple(tuple(map(int, line.split())) for line in in_)

    tree = UnionFindTree(N + 1)
    for a, b in AB:
        tree.unite(a, b)
    
    c = Counter(tree.find(i) for i in range(1, N + 1))
    return c.most_common(1)[0][1]
    

def main():
    answer = resolve(sys.stdin.buffer)
    print(answer)


if __name__ == '__main__':
    main()

Solution (Python):
def gp(u,parent):
	if parent[u] != u: parent[u] = gp(parent[u], parent)
	return parent[u] 
n,m = map(int, raw_input().split())
parent = {i:i for i in range(1,n+1)}
size = {i:1 for i in range(1,n+1)}
for _ in range(m):
	u,v = map(int, raw_input().split())
	pu,pv = gp(u,parent), gp(v,parent)
	if pu != pv:
		parent[pv] = pu
		size[pu] += size[pv]
print max(size.values())

Solution (Python):
n, m = (int(x) for x in input().split())
par = [-1]*(n+1)
def find(x):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x]) 
        return par[x]
def same(x,y):
    return find(x) == find(y)
def unite(x,y):
    x = find(x)
    y = find(y)
    if x == y:
        return 0
    else:
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
def size(x):
    return -par[find(x)]
g = [[] for _ in range(n+1)]
for _ in range(m):
    s,t = map(int,input().split())
    unite(s,t)
    g[s].append(t)
    g[t].append(s)
ma = 0
for i in range(1,n+1):
    ans = size(i)
    if ma<ans:
        ma = ans
print(ma)

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

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

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

        self.parents[x] += self.parents[y]
        self.parents[y] = x
N,M = map(int,input().split())
uf = UnionFind(N)
for m in range(M):
    temp = [int(i)-1 for i in input().split()]
    uf.union(temp[0],temp[1])
print(-min(uf.parents))

Solution (Python):


from collections import defaultdict, deque


N, M = list(map(int, input().split()))
G = defaultdict(set)
for m in range(M):
    A_i, B_i = list(map(int, input().split()))
    G[A_i - 1].add(B_i - 1)
    G[B_i - 1].add(A_i - 1)


seen = [False for i in range(N)]

ans = 0
for i in range(N):
    if seen[i]:
        continue
    friends = 0
    que = deque()

    seen[i] = True
    que.append(i)
    friends += 1

    while len(que) > 0:
        v = que.popleft()
        for w in G[v]:
            if not seen[w]:
                seen[w] = True
                que.append(w)
                friends += 1

    ans = max(ans, friends)


print(ans)

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

Solution (Python):
import sys

sys.setrecursionlimit(10 ** 6)
input = sys.stdin.readline
from math import floor, sqrt, factorial, hypot, log  
from heapq import heappop, heappush, heappushpop
from collections import Counter, defaultdict, deque
from itertools import accumulate, permutations, combinations, product, combinations_with_replacement
from bisect import bisect_left, bisect_right
from copy import deepcopy
from fractions import gcd
from random import randint


def ceil(a, b): return (a + b - 1) // b


inf = float('inf')
mod = 10 ** 9 + 7


def pprint(*A):
    for a in A:     print(*a, sep='\n')


def INT_(n): return int(n) - 1


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


def MF(): return map(float, input().split())


def MI_(): return map(INT_, input().split())


def LI(): return list(MI())


def LI_(): return [int(x) - 1 for x in input().split()]


def LF(): return list(MF())


def LIN(n: int): return [I() for _ in range(n)]


def LLIN(n: int): return [LI() for _ in range(n)]


def LLIN_(n: int): return [LI_() for _ in range(n)]


def LLI(): return [list(map(int, l.split())) for l in input()]


def I(): return int(input())


def F(): return float(input())


def ST(): return input().replace('\n', '')


def main():
    N, M = LI()
    par = [i for i in range(N + 1)]
    par_size = [1 for _ in range(N + 1)]
    def find(x):
        if par[x] == x:
            return x
        else:
            par[x] = find(par[x])
            return par[x]

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

    def unite(x, y):
        if same(x, y):
            return 0
        par_size[find(y)] += par_size[find(x)]
        par[find(x)] = find(y)
    for _ in range(M):
        A, B = LI()
        unite(A, B)
    ans = 0
    for p in par_size:
        ans = max(ans, p)
    print(ans)


if __name__ == '__main__':
    main()

Solution (Python):
from collections import Counter
n, m = map(int, input().split())
ab = [tuple(map(int, input().split())) for _ in range(m)]

if m == 0:
    print(1)
    exit()
    
g = [[] for _ in range(n)]
visited = [-1] * n
for a, b in ab:
    a, b = a-1, b-1
    g[a].append(b)
    g[b].append(a)

def dfs(start):
    global visited
    if visited[start] != -1:
        return 1
    stack = []
    stack.append(start)
    visited[start] = start
    while stack:
        root = stack.pop()
        for j in g[root]:
            if visited[j] == -1:
                visited[j] = start
                stack.append(j)

for i in range(n):
    dfs(i)

tmp = Counter(visited)

p = sorted([v for i, v in tmp.items() if v != 1])
island = len(p)

if island == 1:
    print(n)
else:
    print(p[-1])

Solution (Python):
from collections import Counter
import sys

sys.setrecursionlimit(20000)


def _ia(): return map(int, sys.stdin.readline().strip().split())


class UnionFind:
    def __init__(self, n):
        self._par = [-1]*(n+1)
        self._rnk = [0]*(n+1)

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

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

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


def main():
    n, m = _ia()
    uf = UnionFind(n)
    for _ in range(m):
        a, b = map(lambda x: x-1, _ia())
        uf.unite(a, b)
    c = Counter([uf.root(i) for i in range(n)])
    return max(c.values())


if __name__ == "__main__":
    print(main())

Solution (Python):







"""
Union-find data structure.
"""

from networkx.utils import groups


class UnionFind:
    """Union-find data structure.

    Each unionFind instance X maintains a family of disjoint sets of
    hashable objects, supporting the following two methods:

    - X[item] returns a name for the set containing the given item.
      Each set is named by an arbitrarily-chosen one of its members; as
      long as the set remains unchanged it will keep the same name. If
      the item is not yet part of a set in X, a new singleton set is
      created for it.

    - X.union(item1, item2, ...) merges the sets containing each item
      into a single larger set.  If any item is not yet part of a set
      in X, it is added to X as one of the members of the merged set.

      Union-find data structure. Based on Josiah Carlson's code,
      http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/215912
      with significant additional changes by D. Eppstein.
      http://www.ics.uci.edu/~eppstein/PADS/UnionFind.py

    """

    def __init__(self, elements=None):
        """Create a new empty union-find structure.

        If *elements* is an iterable, this structure will be initialized
        with the discrete partition on the given set of elements.

        """
        if elements is None:
            elements = ()
        self.parents = {}
        self.weights = {}
        for x in elements:
            self.weights[x] = 1
            self.parents[x] = x

    def __getitem__(self, object):
        """Find and return the name of the set containing the object."""

        
        if object not in self.parents:
            self.parents[object] = object
            self.weights[object] = 1
            return object

        
        path = [object]
        root = self.parents[object]
        while root != path[-1]:
            path.append(root)
            root = self.parents[root]

        
        for ancestor in path:
            self.parents[ancestor] = root
        return root

    def __iter__(self):
        """Iterate through all items ever found or unioned by this structure.

        """
        return iter(self.parents)

    def to_sets(self):
        """Iterates over the sets stored in this structure.

        For example::

            >>> partition = UnionFind('xyz')
            >>> sorted(map(sorted, partition.to_sets()))
            [['x'], ['y'], ['z']]
            >>> partition.union('x', 'y')
            >>> sorted(map(sorted, partition.to_sets()))
            [['x', 'y'], ['z']]

        """
        
        for x in self.parents.keys():
            _ = self[x]  

        
        for block in groups(self.parents).values():
            yield block

    def union(self, *objects):
        """Find the sets containing the objects and merge them all."""
        roots = [self[x] for x in objects]
        
        heaviest = max(roots, key=lambda r: self.weights[r])
        for r in roots:
            if r != heaviest:
                self.weights[heaviest] += self.weights[r]
                self.parents[r] = heaviest


def main():
    N, M = map(int, input().split())
    AB = [list(map(int, input().split())) for _ in range(M)]

    u = UnionFind(range(1, N + 1))

    for a, b in AB:
        u.union(a, b)

    li = list(u.to_sets())

    ans = 0
    for p in li:
        if len(p) > ans:
            ans = len(p)
    print(ans)


main()

Solution (Python):
from collections import deque

N, M = [int(s) for s in input().split()]
edge = [[int(s) - 1 for s in input().split()] for _ in range(M)]
graph = [[] for _ in range(N)]

for i, j in edge:
    graph[i].append(j)
    graph[j].append(i)

group = [0] * N
group_num = 0
visited = [False] * N

group_nums = [0] * N

for i in range(N):
    if visited[i]:
        continue
    dq = deque([i])
    group[i] = group_num
    visited[i] = True
    group_nums[group_num] += 1
    while(dq):
        search_obj = dq.pop()
        for candidate_obj in graph[search_obj]:
            if not visited[candidate_obj]:
                group[candidate_obj] = group_num
                dq.appendleft(candidate_obj)
                visited[candidate_obj] = True
                group_nums[group_num] += 1
    group_num += 1

print(max(group_nums))

Solution (Python):
import sys
class UnionFind:
    def __init__(self, n):
        
        
        self.table = [-1] * n
 
    def _root(self, x):
        stack = []
        tbl = self.table
        while tbl[x] >= 0:
            stack.append(x)
            x = tbl[x]
        for y in stack:
            tbl[y] = x
        return x
 
    def find(self, x, y):
        return self._root(x) == self._root(y)
 
    def union(self, x, y):
        r1 = self._root(x)
        r2 = self._root(y)
        if r1 == r2:
            return
        
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            if d1 == d2:
                self.table[r1] -= 1
        else:
            self.table[r1] = r2
 
 
if __name__ == '__main__':
    sys.setrecursionlimit(1000000)
    n,m=map(int,sys.stdin.readline().split())
    ins = UnionFind(n+1)
    for i in range(m):
        a,b= map(int, sys.stdin.readline().split())
        ins.union(a,b)
    """
    ins.union(0, 1)
    ins.union(2, 3)
    print(ins.find(0, 3))  
    ins.union(1, 2)
    print(ins.find(0, 3))  
    """
    cnt=[0 for i in range(n+1)]
    for i in range(1,n+1):
        cnt[ins._root(i)]+=1
    print(max(cnt))

Solution (Python):





"""
"""

from collections import defaultdict
from itertools import accumulate
import bisect

import sys
input = sys.stdin.readline

def solve(n,m):
    graph = defaultdict(list)
    for _ in range(m):
        a, b = map(int,input().split())
        a -= 1
        b -= 1
        graph[a].append(b)
        graph[b].append(a)
    connected = []
    unseen = set(range(n))
    while unseen:
        aa = unseen.pop()
        unseen.add(aa)
        stack = [aa]
        cnt = 0
        while stack:
            bb = stack.pop()
            if bb in unseen:
                stack.extend(graph[bb])
                unseen.remove(bb)
                cnt += 1
        connected.append(cnt)
    
    print(max(connected))
            


            

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


if __name__ == "__main__":
    main()