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

Solution (Python):
n,m=map(int,input().split())
p=[(i,1)for i in range(n)]
def find(i):
  if p[i][0]==i:return i
  else:
    c=find(p[i][0])
    p[i]=(c,0)
    return c
def union(i,j):
  pi=find(i)
  pj=find(j)
  if not pi==pj:
    if p[pi][1]>p[pj][1]:
      p[pi]=(pi,p[pi][1]+p[pj][1])
      p[pj]=(pi,0)
    else:
      p[pj]=(pj,p[pi][1]+p[pj][1])
      p[pi]=(pj,0)
      

for i in range(m):
  a,b=map(int,input().split())
  union(a-1,b-1)
ans=0
for i in range(n):
  if p[i][0]==i:ans=max(ans,p[i][1])
print(ans)

Solution (Python):

from collections import defaultdict


n,m=map(int,input().split())
d=defaultdict(int)
parent=[-1]*(n+1)
def find(a):
    if parent[a]<0:
        return a
    parent[a]=find(parent[a])
    return parent[a]
    
    
    
    
    
    
    
    

def union(a,b):
    parent[a]+=parent[b]
    parent[b]=a
    d[parent[a]]+=d[parent[b]]+1
for i in range(m):
    a,b= map(int, input().split())
    if a>b:a,b=b,a
    a=find(a)
    b=find(b)
    if a!=b:
        union(a,b)
ans=0

for x in parent[1:]:
    x=-x
    ans=max(ans,x)
print(ans)

Solution (Python):
import sys
from collections import deque
INF = float('inf')
n,m = map(int, sys.stdin.readline().rstrip("\n").split())
edge = [[] for _ in range(n)]
for _ in range(m):
    a,b = map(int, sys.stdin.readline().rstrip("\n").split())
    edge[a-1].append(b-1)
    edge[b-1].append(a-1)
for _ in range(n):
    edge[_] = list(set(edge[_]))
done = [False]*n
d = deque()
gmax = -INF
for i in range(n):
    if not done[i]:
        done[i] = True
        d.append(i)
        g = 1
        while d:
            cp = d.pop()
            for np in edge[cp]:
                if not done[np]:
                    done[np] = True
                    d.append(np)
                    g += 1
        gmax = max(gmax,g)
print(gmax)

Solution (Python):
f=lambda:map(int,input().split())
n,m=f()
p=[-1]*n
def root(x):
  while p[x]>=0: x=p[x]
  return x
def unite(x,y):
  x,y=root(x),root(y)
  if x==y: return
  if x>y: x,y=y,x
  p[x]+=p[y]
  p[y]=x
for i in range(m):
  a,b=f()
  unite(a-1,b-1)
print(-min(p))

Solution (Python):
from collections import Counter


class UnionFind:

    def __init__(self, size):
        self.size = size
        self.par = list(range(size))
        self.rank = [0]*size

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

    def unite_tree(self, x, y):
        x, y = self.find_par(x), self.find_par(y)
        if x == y:
            return

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

    def in_the_same(self, x, y):
        return self.find_par(x) == self.find_par(y)


if __name__ == "__main__":
    N, M = map(int, input().split())
    uf = UnionFind(N)
    C = Counter()
    for _ in range(M):
        a, b = map(lambda x: int(x)-1, input().split())
        uf.unite_tree(a, b)
    for i in range(N):
        C[uf.find_par(i)] += 1
    print(C.most_common()[0][1])

Solution (Python):
from scipy.sparse.csgraph import connected_components
from scipy.sparse import csr_matrix

n,m=[int(i) for i in input().split()]
data=[1]*m

row=[]
col=[]

for i in range(m):
    one,two=[int(i) for i in input().split()]
    n_one=min(one-1,two-1)
    n_two = max(one - 1, two - 1)
    row.append(n_one)
    col.append(n_two)

graph=csr_matrix((data,(row,col)),shape=(n,n))
num,label=connected_components(graph)

count_num=[0]*n
for i in label:
    count_num[i]+=1

print(max(count_num))

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents =[-1 for i in range(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 False
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        self.parents[x] += self.parents[y]
        self.parents[y] = x
        return True

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


N, M = map(int, input().split())
uf = UnionFind(N)
X = [[] for _ in range(M)]
for i in range(M):
    X[i] = list(map(int, input().split()))
    uf.unite(X[i][0]-1, X[i][1]-1)
print(-min(uf.parents))

Solution (Python):
from collections import deque

N, M = map(int, input().split())
S = [set() for i in range(N)]
visited = [-1] * N
colorcount = [-1] * N

for i in range(M):
    a, b = map(int, input().split())
    a -= 1
    b -= 1
    S[a].add(b)
    S[b].add(a)

q = deque()
for i in range(N):
    q.append(i)
    color = i
    cnt = 1
    while len(q):
        nt = q.popleft()
        if visited[nt] != -1:
            continue
        visited[nt] = color
        q.extend(S[nt])
        cnt += 1
    colorcount[color] = cnt - 1

print(max(colorcount))

Solution (Python):
import sys
from io import StringIO
import unittest
import os


sys.setrecursionlimit(999999999)


class UnionFind:
    def __init__(self, n):
        """
        コンストラクタ
        :要素数 n:
        """
        self.n = n
        
        
        
        self.parents = [-1] * n

    def getroot(self, x):
        """
        データが属するグループのID(と考えて良いはず)を取得する。
        :調査するグループ x:
        """
        
        if self.parents[x] < 0:
            return x
        else:
            
            
            self.parents[x] = self.getroot(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        """
        2つのデータが属するグループを結合する。
        :結合するデータ(1つ目) x:
        :結合するデータ(2つ目) y:
        """
        
        x = self.getroot(x)
        y = self.getroot(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):
        """
        指定したグループに属するデータの数を返す。
        :調査グループ x:
        """
        
        return -self.parents[self.getroot(x)]

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

    def members(self, x):
        """
        指定したグループに属するデータの一覧を返す。size()と比較して速度が圧倒的に遅いので注意。
        :調査グループ x:
        """
        root = self.getroot(x)
        return [i for i in range(self.n) if self.getroot(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(test_def_name=""):
    n, m = map(int, input().split())
    ab_s = [list(map(int, input().split())) for i in range(m)]

    work_abs = []
    for ab in ab_s:
        a = min(ab[0], ab[1])
        b = max(ab[0], ab[1])
        work_abs.append([a, b])

    ab_s = list(map(list, set(map(tuple, work_abs))))

    uf = UnionFind(n + 1)

    for a, b in ab_s:
        uf.union(a, b)

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

    print(ans)



class TestClass(unittest.TestCase):
    def assertIO(self, assert_input, output):
        stdout, sat_in = sys.stdout, sys.stdin
        sys.stdout, sys.stdin = StringIO(), StringIO(assert_input)
        resolve(sys._getframe().f_back.f_code.co_name)
        sys.stdout.seek(0)
        out = sys.stdout.read()[:-1]
        sys.stdout, sys.stdin = stdout, sat_in
        self.assertEqual(out, output)

    def test_input_1(self):
        test_input = """5 6
1 2
2 1
3 4
1 2
2 1
5 1"""
        output = """3"""
        self.assertIO(test_input, output)

    def test_input_2(self):
        test_input = """4 10
1 2
2 1
1 2
2 1
1 2
1 3
1 4
2 3
2 4
3 4"""
        output = """4"""
        self.assertIO(test_input, output)

    def test_input_3(self):
        test_input = """10 4
3 1
4 1
5 9
2 6"""
        output = """3"""
        self.assertIO(test_input, output)

    
    def test_original(self):
        pass



if __name__ == "__main__":
    if os.environ.get("USERNAME") is None:
        
        resolve()

    else:
        
        unittest.main()

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

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

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

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

        if x == y:
            return

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

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

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

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

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

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

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

    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(self):
      return max([len(self.members(r)) for r in self.roots()])
uf = UnionFind(N)

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

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

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

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

        if x == y:
            return

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

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

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

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)

cnt = 0
for pa in uf.par:
    cnt = min(pa, cnt)
print(-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 max_group_members(self):
        return -min([i for i in self.parents if i<0])
    
N,M = map(int,input().split())

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

print(uf.max_group_members())

Solution (Python):
import sys
import bisect
import itertools
import collections
import fractions
import heapq
import math
from operator import mul
from functools import reduce
from functools import lru_cache


def solve():
    readline = sys.stdin.buffer.readline
    mod = 10 ** 9 + 7
    N, M = map(int, input().split())
    friend = [[] for _ in range(N + 1)]
    for _ in range(M):
        a,b = map(int, input().split())
        friend[a].append(b)
        friend[b].append(a)
    notchecked = set(list(range(1, N+1)))
    group = [0]*(N+1)
    nowgroup = 1
    while len(notchecked) > 0:
        now = collections.deque([notchecked.pop()])
        while len(now) > 0:
            d = now.popleft()
            group[d] = nowgroup
            notchecked.discard(d)
            for f in friend[d]:
                if f in notchecked:
                    group[f] = nowgroup
                    now.append(f)
                else:
                    continue
        nowgroup += 1
    countdic = {}
    for i in group:
        if i not in countdic:
            countdic[i] = 1
        else:
            countdic[i] += 1
    ans = max(countdic.values())
    print(ans)


if __name__ == '__main__':
    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(-min(uf.parents))

Solution (Python):



import sys
from collections import deque
from collections import defaultdict
from collections import Counter
import heapq
import collections
import itertools
import bisect
import copy
sys.setrecursionlimit(10**6)




def zz(): return list(map(int, sys.stdin.readline().split()))


def z(): return int(sys.stdin.readline())


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


def C(line): return [sys.stdin.readline() for _ in range(line)]


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 = zz()
A = [0]*M
B = [0] * M
tree = UnionFind(N)


for i in range(M):
    a, b = zz()
    a -= 1
    b -= 1
    
    tree.union(a, b)
ans = 0
for p in tree.parents:
    ans = max(ans, tree.size(p))
if (ans == 0):
    print(N)
else:
    print(ans)

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

n, m = map(int, input().split())
ans = [0 for _ in range(n)]
trees = [[] for _ in range(n)]

for _ in range(m):
    a,b=map(int,input().split())
    trees[a-1].append(b-1)
    trees[b-1].append(a-1)

visited = [False]*n
def dfs(n):
    visited[n] = True
    global temp
    temp+=1
    for i in trees[n]:
        if visited[i]:
            continue
        dfs(i)

ans=0
for x in range(n):
    if visited[x]:
        continue
    temp=0
    dfs(x)
    ans=max(temp,ans)
print(ans)

Solution (Python):
import collections

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

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

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

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

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

for i in range(M):
    A, B = map(int, input().split())
    tree.unite(A-1, B-1)

roots = [tree.find(p) for p in tree.parent]
count = collections.Counter(roots).most_common(1)[0][1]
print(count)

Solution (Python):

import sys,io,os,time
from collections import defaultdict
from collections import OrderedDict
from collections import deque
from itertools import combinations
from itertools import permutations
import bisect,math,heapq
alphabet = "abcdefghijklmnopqrstuvwxyz"

input = sys.stdin.readline


class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))

    def find(self, a):
        acopy = a
        while a != self.parent[a]:
            a = self.parent[a]
        while acopy != a:
            self.parent[acopy], acopy = a, self.parent[acopy]
        return a

    def union(self, a, b):
        self.parent[self.find(b)] = self.find(a)




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

uf = UnionFind(n)
for ii in range(m):
	u,v = map(int , input().split())
	u-=1
	v-=1
	uf.union(u,v)
c = [0]*n
for i in range(n):
	c[uf.find(i)] += 1
print(max(c))



'''
import collections,sys,threading
sys.setrecursionlimit(10**9)
threading.stack_size(10**8)







def solve():
	n , m = map(int , input().split())
	dic = defaultdict(set)
	for ii in range(m):
		u,v = map(int , input().split())
		dic[u].add(v)
		dic[v].add(u)
	l = []
	visited = [0]*(n+2)
	def f(node):
		visited[node] = True
		temp = 0
		for nei in dic[node]:
			if not visited[nei]:
				temp += f(nei)
				
		return temp
	for i in range(1,n+1):
		if not visited[i]:
			l.append(f(i)+1)
	
	
	print(max(l))


threading.Thread(target=solve).start()

'''

Solution (Python):
import sys
import numpy as np
import math  
from collections import deque
from collections import defaultdict
from copy import deepcopy
from itertools import accumulate 
def input(): return sys.stdin.readline().rstrip()
from functools import lru_cache 
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 max_members_group(self):
        return max([self.size(r) for r in self.roots()])

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

    
    
    

def main():
    n, m = list(map(int,input().split()))
    data = [input().split() for _ in range(m)]
 
    UF = UnionFind(n)
    for i in range(m):
        UF.union(int(data[i][0]) - 1, int(data[i][1]) - 1)
    print(UF.max_members_group())
    
    return 0

if __name__ == "__main__":
    main()

Solution (Python):
def main():

    n,m = map(int,input().split())
    ary = []
    for i in range(m):
        aa, bb = map(int,input().split())

        ary.append((aa-1,bb-1))
    ary_s = list(set(ary))
    a = []
    
    
    uf = UnionFind(n)

    for i in range(len(ary_s)):
        a.append(ary_s[i][0])
        a.append(ary_s[i][1])
        uf.union(ary_s[i][0], ary_s[i][1])
    ans = 1
    for i in a:
        ans = max(ans, uf.size(i))
    print(ans)

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

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 {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 = list(map(int, input().split()))
friends = []
for i in range(m):
    f = list(map(int, input().split()))
    friends.append(f)

friend_map = UnionFind(n)

for f in friends:
    friend_map.union(f[0]-1, f[1]-1)

ans = 0
for i in range(n):
    tmp = friend_map.size(i)
    ans = max(ans, tmp)

print(ans)

Solution (Python):
N,M=[int(s) for s in input().split()] 
hito=[0 for i in range(N)]
edge=[set() for _ in range(N)]
for i in range(M):
  a,b=[int(s) for s in input().split()]
  edge[a-1].add(b-1)
  edge[b-1].add(a-1)


def dfs(start):
  count=1
  reach=set()
  reach.add(start)
  hito[start]=1
  while reach:
    _from=reach.pop()
    for _to in edge[_from]:
      if not(_to in reach) and hito[_to]==0:
        reach.add(_to)
        count+=1
        hito[_to]=1
  return(count)
 

ans=set()
for h in range(N):
  if hito[h]==0:
    ans.add(dfs(h))
print(max(ans))

Solution (Python):
import sys

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

sys.setrecursionlimit(10**7)

v_neighbor = [[] for _ in range(N)]
for _ in range(M):
    a, b = map(int, input().split())
    v_neighbor[a-1].append(b-1)
    v_neighbor[b-1].append(a-1)


v_visit = [False for _ in range(N)]

def search(n):
    count = 0
    for n_ in set(v_neighbor[n]):
        if not v_visit[n_]:
            v_visit[n_] = True
            count += 1
            count += search(n_)
    return count

res = 1
for i in range(N):
    if v_visit[i]:
        continue
    search_res = search(i)
    res = max(res, search_res)


print(res)

Solution (Python):
from collections import defaultdict
d= defaultdict(list)
n,m = [int(i) for i in input().split()]
visited = [False for i in range(n)]
for i in range(m):
    a,b=  map(int,input().split())
    a-=1
    b-=1
    d[a].append(b)
    d[b].append(a)
def dfs(a):
    count = 0
    stack = [a]
    while(stack):
        curr = stack.pop()
        count+=1
        visited[curr]=True
        for i in d[curr]:
            if visited[i]==False:
                visited[i]=True
                stack.append(i)
        
    return count
ca=0
for i in range(n):
    if visited[i]==False:
        c= dfs(i)
        ca = max(ca,c)
print(ca)

Solution (Python):

import math
import bisect
import copy
import time
from collections import Counter
from itertools import combinations


n,m=map(int,input().split())
d={i:set() for i in range(1,n+1)}
for i in range(m):
	x,y=map(int,input().split())
	d[x].add(y)
	d[y].add(x)


vis={i:False for i in range(1,n+1)}
for u,v in d.items():
	d[u]=list(v)
count=0
que=[]
for i in range(1,n+1):
	if not vis[i]:
		que=[]
		c=1
		vis[i]=True
		que.append(i)
		while len(que)!=0:
			x=que.pop(0)
			for j in d[x]:
				if not vis[j]:
					vis[j]=True
					c+=1
					que.append(j)
		count=max(c,count)

print(count)

Solution (Python):
N, M = list(map(int, input().split()))
edges = []
for _i in range(M):
    edges.append(list(map(int, input().split())))

import networkx as nx

G = nx.Graph()
G.add_edges_from(edges)
ans = 1
for comp in nx.connected_components(G):
    
    
    ans = max(ans, len(comp))
print(ans)

Solution (Python):


import sys
from collections import deque
si = sys.stdin.readline


def main():
    [n, m] = [int(e) for e in si().split()]
    if not m:
        print(1)
        return

    visited = [False]*(n+1)
    fm = [set() for _ in range(n+1)]
    mx, comp = 0, 0

    while m:
        m -= 1
        [a, b] = [int(e) for e in si().split()]
        fm[a].add(b)
        fm[b].add(a)

    for i in range(1, n+1):
        if visited[i]:
            continue
        visited[i] = True
        comp += 1
        q = deque()
        q.append(i)
        cnt = 1
        while q:
            curr = q.popleft()
            for e in fm[curr]:
                if not visited[e]:
                    visited[e] = True
                    q.append(e)
                    cnt += 1
        mx = max(mx, cnt)
    print(mx)

if __name__ == '__main__':
    main()

Solution (Python):
from collections import deque
n,m=map(int,input().split())
ans=0


group = [set() for _ in range(n)]

for i in range(m):
    a,b = map(int,input().split())
    a-=1
    b-=1
    group[a].add(b)
    group[b].add(a)


kisyutu = set()
deque = deque()

for i in range(n):
    if i not in kisyutu:
        kisyutu.add(i)
        friend_set=group[i]

        deque.extend(group[i])

        while deque:
            a1 = deque.pop()
            if a1 not in kisyutu:
                kisyutu.add(a1)
                friend_set.add(a1)
                deque.extend(group[a1])
        ans = max(ans, len(friend_set)+1)

if m!=0:
    print(ans)
else:
    print(1)

Solution (Python):
n,m=map(int,input().split())
g = [[] for _ in range(n)] 
from collections import deque
for _ in range(m):
    a, b = [int(x) for x in input().split()]
    g[a-1].append(b)
    g[b-1].append(a)

def bfs(u):
    queue = deque([u])
    d = [None] * n 
    d[u] = 0 
    while queue:
        v = queue.popleft()
        for i in g[v]:
            if d[i] is None:
                d[i] = d[v] + 1
                queue.append(i)
x=[0]*n
s=1
m=0
for i in range(1,n+1):
    if x[i-1]==0:
        x[i-1]=s
        c=1
        q=deque([i])
        while q:
            v = q.popleft()
            for j in g[v-1]:
                if x[j-1]==0:
                    q.append(j)
                    x[j-1]=s
                    c+=1
        s+=1
        m=max(m,c)
print(m)

Solution (Python):
from collections import deque, defaultdict


def main():
    people_count, info_count = [int(x) for x in input().split()]
    if info_count == 0:
        return 1
    if info_count == 1:
        return 2

    friends = [set() for _ in range(people_count)]
    for _ in range(info_count):
        a, b = [int(x) - 1 for x in input().split()]
        friends[a].add(b)
        friends[b].add(a)
    seen = [False] * people_count
    circle_id = 0
    counter = defaultdict(int)
    for i, circle in enumerate(friends):
        if seen[i]:
            continue
        circle_id += 1
        qu = deque()
        qu.append(i)
        seen[i] == 1
        while qu:
            now = qu.popleft()
            for new in friends[now]:
                if seen[new]:
                    continue
                qu.append(new)
                seen[new] = True
                counter[circle_id] += 1
    return max(v for v in counter.values())


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