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 UnionFind:
    def __init__(self,n):
        self.parent = [i for i in range(n)]
        self.size = [1]*n

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

    def unite(self,a,b):
        a_root = self.find(a)
        b_root = self.find(b)
        if a_root == b_root:
            return
        else:
            if self.size_of(b_root) > self.size_of(a_root): 
                self.parent[a_root] = self.parent[b_root]
                self.size[b_root] += self.size[a_root]
            else:
                self.parent[b_root] = self.parent[a_root]
                self.size[a_root] += self.size[b_root]
                
    def size_of(self,a):
        return self.size[self.find(a)]
    
    def is_same(self,a,b):
        return self.find(a) == self.find(b)

N,M = map(int,input().split())
tree = UnionFind(N)
for i in range(M):
    X, Y = map(int,input().split())
    tree.unite(X-1,Y-1)

print(max([tree.size_of(x) for x in range(N)]))

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

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


visited = [0]*N 
ans = 0
for i in range(N):
    if visited[i]:
        continue
    tmp = list(friends[i])
    ans_tmp = 1
    visited[i] = 1
    while tmp:
        t = tmp.pop()
        if not visited[t]:
            visited[t] = 1
            ans_tmp += 1
            for j in friends[t]:
                tmp.append(j)

    ans = max(ans, ans_tmp)
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.n = n
        self.parent = [i for i in range(n)]  
        self.rank = [1] * n  
        self.size = [1] * 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:
            if self.rank[x] < self.rank[y]:
                self.parent[x] = y
                self.size[y] += self.size[x]
            else:
                self.parent[y] = x
                self.size[x] += self.size[y]
                if self.rank[x] == self.rank[y]:
                    self.rank[x] += 1

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

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


N, M = map(int, input().split())
A, B = [0] * M, [0] * M  

direct =[[] for _ in range(N)]  
uf = UnionFind(N)  

for i in range(M):
    A[i], B[i] = map(int, input().split())
    A[i] -= 1
    B[i] -= 1
    direct[A[i]].append(B[i])
    direct[B[i]].append(A[i])
    uf.unite(A[i], B[i])

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

Solution (Python):
N,M = [int(x) for x in input().split()]

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

def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True


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


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



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

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

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

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

        if x == y:
            return

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

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

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

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

Solution (Python):





def int_mtx(N):
    x = []
    for _ in range(N):
        x.append(list(map(int,input().split())))
    return np.array(x)

def str_mtx(N):
    x = []
    for _ in range(N):
        x.append(list(input()))
    return np.array(x)

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

def int_list():
    return list(map(int,input().split()))

def print_space(l):
    return print(" ".join([str(x) for x in l]))


import collections as col

import numpy as np
from scipy.sparse.csgraph import connected_components
from scipy.sparse import csr_matrix



N,M = int_map()

i = []
j = []

for z in range(0,M):
    a,b = int_map()
    i.append(a-1)
    j.append(b-1)
    
d = [1]*M

csr = csr_matrix((d,(i,j)),(N,N))


n, labels = connected_components(csr)

ll = list(labels)
aa = col.Counter(ll)
print(aa.most_common()[0][1])

Solution (Python):
from bisect import *
from collections import *
from itertools import *
import functools
import sys
import math
from decimal import *
from copy import *
from heapq import *
from fractions import *
getcontext().prec = 30
MAX = sys.maxsize
MAXN = 1000010
MOD = 10**9+7
spf = [i for i in range(MAXN)]
spf[0]=-1
def sieve():
    for i in range(2,MAXN,2):
        spf[i] = 2
    for i in range(3,int(MAXN**0.5)+1):
        if spf[i]==i:
            for j in range(i,MAXN,i):
                if spf[j]==j:
                    spf[j]=i
def fib(n,m):
    if n == 0:
        return [0, 1]
    else:
        a, b = fib(n // 2)
        c = ((a%m) * ((b%m) * 2 - (a%m)))%m
        d = ((a%m) * (a%m))%m + ((b)%m * (b)%m)%m
        if n % 2 == 0:
            return [c, d]
        else:
            return [d, c + d]
 
def charIN(x= ' '):
    return(sys.stdin.readline().strip().split(x))
 
def arrIN(x = ' '):
    return list(map(int,sys.stdin.readline().strip().split(x)))
 
def ncr(n,r):
    num=den=1
    for i in range(r):
        num = (num*(n-i))%MOD
        den = (den*(i+1))%MOD
 
    return (num*(pow(den,MOD-2,MOD)))%MOD
 
def flush():
    return sys.stdout.flush()




'''*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*'''

def bfs(v):
    q = [v]
    vis[v] = 1
    l = 0
    while q:
        x = q.pop(0)
        l+=1
        for i in d[x]:
            if not vis[i]:
                vis[i] = 1
                q.append(i)
    return l


n,m = arrIN()
d = defaultdict(set)

for _ in range(m):
    a,b = arrIN()
    d[a].add(b)
    d[b].add(a)

vis = defaultdict(int)
cc = []
for i in range(1,n+1):
    if not vis[i]:
        cc.append(bfs(i))

cc.sort()
ans = cc[0]
cl = cc[0]
t = cl
for i in cc[1:]:
    if i==cl:
        continue
    cl = i-t
    t+=cl
    ans+=cl
print(ans)

Solution (Python):

import sys
import threading


sys.setrecursionlimit(10**7) 
threading.stack_size(2**29)  

visited = set()

def explore(adj, x, comp, cc):
    visited.add(x)
    if not(cc in comp):
        comp[cc] = []
    comp[cc].append(x)
    for w in adj[x]:
        if not (w in visited):
            explore(adj, w, comp, cc)

def number_of_components(adj, n):
    
    cc = 0
    comp = dict()
    for v in range(n):
        if not(v in visited):
            explore(adj, v, comp, cc)
            cc += 1
    return comp


def main():
    n, m = map(int, input().split())
    adj = [[] for _ in range(n)]
    for _ in range(m):
        a, b = map(int, input().split())
        adj[a - 1].append(b - 1)
        adj[b - 1].append(a - 1)
    res = number_of_components(adj, n)
    max_ = 0
    for value in res.values():
        max_ = max(max_, len(value))
    print(max_)
    


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

Solution (Python):
def resolve():
    from collections import defaultdict, deque
    N, M = [int(i) for i in input().split()]
    AABB = [[int(i) - 1 for i in input().split()] for _ in range(M)]
    dic = defaultdict(set)
    for a, b in AABB:
        dic[a].add(b)
        dic[b].add(a)
    groups = [-1 for _ in range(N)]
    group = 0
    groupmemcnt = [0 for _ in range(N)]
    for i in range(N):
        if groups[i] != -1:
            continue
        groups[i] = group
        groupmemcnt[group] += 1
        que = deque(list(dic[i]))
        while len(que) > 0:
            j = que.popleft()
            if groups[j] != -1:
                continue
            groups[j] = group
            groupmemcnt[group] += 1
            que.extend(list(dic[j]))
        group += 1
    print(max(groupmemcnt))
    return

resolve()

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


uf = UnionFind(N)

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

maxSize = 0
for x in range(N):
    maxSize = max(maxSize, uf.size(x))
print(maxSize)

Solution (Python):


n, m = map(int, input().split())
set_dict = {}
chech_list = [0] * (n + 1)
for i in range(m):
    a, b = map(int, input().split())
    if a in set_dict:
        set_dict[a].add(b)
    else:
        set_dict[a] = {b}
    if b in set_dict:
        set_dict[b].add(a)
    else:
        set_dict[b] = {a}
    chech_list[a] = 1
    chech_list[b] = 1

ans = 1
for i in range(1, n + 1):
    if chech_list[i] == 0:
        continue
    count = 0
    temp_set = set_dict[i]
    while len(temp_set) > 0:
        x = temp_set.pop()
        count += 1
        chech_list[x] = 0
        for y in set_dict[x]:
            if chech_list[y] == 1:
                temp_set.add(y)
    ans = max(count, ans)
print(ans)

Solution (Python):
import sys

sys.setrecursionlimit(1000000)


N, M = map(int, input().split())
C = [set([]) for i in range(N)]


def dfs(n, y):
    seen[n] = True
    y += 1
    for c in C[n]:
        if seen[c]:
            continue
        else:
            y = dfs(c, y)
    return y


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

ans = 0
seen = [False] * N
for i in range(N):
    if seen[i]:
        continue
    x = 0
    x = dfs(i, x)
    ans = max(ans, x)

print(ans)

Solution (Python):



from collections import deque




def solve(N, M, ABs):
    f_map = [[] for _ in range(N + 1)]
    for A, B in ABs:
        f_map[A].append(B)
        f_map[B].append(A)
    group = [-1] * (N + 1)
    latest_gnum = 1
    for i in range(1, N  + 1):
        if group[i] != -1:
            continue
        group[i] = latest_gnum
        latest_gnum += 1
        dq = deque([i])
        while dq:
            n = dq.popleft()
            for f in f_map[n]:
                if group[f] != -1:
                    continue
                group[f] = group[n]
                dq.append(f)
    group_sum = [0] * latest_gnum
    for g in group[1:]:
        group_sum[g] += 1
    print(max(group_sum))


if __name__ == '__main__':
    
    
    N, M = map(int, input().split())
    ABs = [[int(i) for i in input().split()] for _ in range(M)]
    
    solve(N, M, ABs)

Solution (Python):
N, M = map(int, input().split())
A, B = [], []
for _ in range(M):
    a, b = map(int, input().split())
    A.append(a)
    B.append(b)

friends = [-1] * (N+1)
number = [1] * (N+1)

for i in range(M):
    k = A[i]
    l = B[i]
    while True:
        if friends[k] == -1:
            break
        k = friends[k]

    while True:
        if friends[l] == -1:
            break
        l = friends[l]
    if k == l:
        continue
    if number[k] >= number[l]:
        friends[l] = k
        number[k] += number[l]
        number[l] = 0
    else:
        friends[k] = l
        number[l] += number[k]
        number[k] = 0

print(max(number))

Solution (Python):
import sys
N, M = map(int, input().split())
REL = [set() for _ in range(N)]
for _ in range(M):
    a, b = map(int, sys.stdin.readline().split())
    REL[a-1].add(b-1)
    REL[b-1].add(a-1)
REL = [list(s) for s in REL]

ans = 0
todo = []
done = set()
pdone = set()
for s in range(N):
    if s in done:
        continue
    pdone.clear()
    todo.append(s)
    while todo:
        p = todo.pop()
        pdone.add(p)
        done.add(p)
        for np in REL[p]:
            if np in pdone:
                continue
            todo.append(np)
    ans = max(ans, len(pdone))
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())



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

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

print(ans)

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


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

G=[[] for i in range(n)]

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



dist=[-1 for i in range(n)]



count=0
def bfs(G):
    global count
    
    if not que:
        return
    v = que.popleft()

    for nv in G[v]:
        if dist[nv] != -1:
            continue
        dist[nv]=dist[v]+1
        que.append(nv)
    count+=1
    
    bfs(G)

ans=0
for i in range(n):
    count=0
    if dist[i] != -1:
        continue
    else:
        que=deque([i])
        dist[i]=0
        bfs(G)
        if ans < count:
            ans=count

print(ans)

Solution (Python):
n,m=list(map(int,input().split()))
par=[i for i in range(n)]
ro=dict()

for i in range(n):
    ro[i]=1
def root(i):
    if par[i]==i:
        return i
    else:
        a=root(par[i])
        par[i]=a
        return a

def unite(x,y):
    rx=root(x)
    ry=root(y)
    if rx!=ry:
        par[rx]=ry
        ro[ry]+=ro[rx]
        ro[rx]=0

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

print(max(ro.values()))

Solution (Python):
N,Q = map(int,input().split())
ab=[list(map(int,input().split()))for _ in range(Q)]
par = [i for i in range(N+1)]
rank = [0]*(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):
    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 a,b in ab:
    unite(a,b)
for a,b in ab:
    unite(a,b)

from collections import*
C=Counter(par)
A=max(C.values())
print(A)

Solution (Python):
def resolve():
    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())
        a -= 1
        b -= 1
        uf.union(a, b)
    ans = 0
    for i in range(n):
        ans = max(ans, uf.size(i))
    print(ans)
resolve()

Solution (Python):
def findgraphs(nodes):
    graphs = []
    while nodes:
        graph = set()
        queue = set([next(iter(nodes))])
        while queue:
            nextq = set()
            graph.update(queue)
            for q in queue:
                nextq.update(n for n in nodes[q] if n not in graph)
                del nodes[q]

            queue = nextq

        graphs.append(graph)

    return graphs




friends = dict()
N, M = map(int, input().split())
nodes = {x : set() for x in range(1, N+1)}
for _ in range(M):
    A, B = map(int, input().split())
    nodes[A].add(B)
    nodes[B].add(A)
graphs = findgraphs(nodes)

m = max(len(g) for g in graphs)
print(m)

Solution (Python):
from collections import Counter
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parent = [i for i in range(n)]
        self.rank = [0 for i in range(n)]

    def getParent(self):
        return [self.find(i) for i in range(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):
        root_x = self.find(x)
        root_y = self.find(y)
        if (root_x == root_y):
            return
        elif self.rank[root_x] > self.rank[root_y]:
            self.parent[root_y] = root_x

        elif self.rank[root_y] > self.rank[root_x]:
            self.parent[root_x] = root_y

        else:
            self.parent[root_x] = root_y
            self.rank[root_y] += 1

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

    def memsInGroup(self, x):
        """
        O(N)かかります
        """
        root = self.find(x)
        return [i for i in range(N) if root == self.find(i)]

    def sizeOfGroup(self, x):
        return len(self.memsInGroup(x))


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

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

roots = friend.getParent()
counts = Counter(roots)

ans = max(counts.values())
print(ans)

Solution (Python):

import sys
import networkx as nx

def solve(N: int, M: int, A: "List[int]", B: "List[int]"):
    G=nx.Graph()

    if M == 0 :
        print(1)
        return

    for a, b in zip(A,B):
        G.add_edge(a, b)

    Gc = max(nx.connected_components(G), key=len)
    print(len(Gc))
    return



def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  
    M = int(next(tokens))  
    A = [int()] * (M)  
    B = [int()] * (M)  
    for i in range(M):
        A[i] = int(next(tokens))
        B[i] = int(next(tokens))
    solve(N, M, A, B)

if __name__ == '__main__':
    main()

Solution (Python):
from collections import deque

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

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

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

    friendsetlist[a].add(b)
    friendsetlist[b].add(a)

dq = deque([])

checked = [0 for _ in range(n)]

ans = 0

for i in range(n):
    if checked[i] == 0:
        dq.append(i)
        checked[i] = 1
        tmpans = 1
        while len(dq) != 0:
            now = dq.popleft()
            for nxt in friendsetlist[now]:
                if checked[nxt] == 0:
                    tmpans += 1
                    dq.append(nxt)
                    checked[nxt] = 1
        if ans < tmpans:
            ans = tmpans

print(ans)

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

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

	def 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):
		ret = defaultdict(list)
		for i in range(self.n):
			ret[self.find(i)].append(i)
		return ret

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

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

for _ in range(m):
	a,b = map(int, input().split())
	uf.union(a, b)
MA = 0
for i in range(n+1):
	if MA <= uf.size(i):
		MA = uf.size(i)
print(MA)

Solution (Python):
from collections import deque
N, M = map(int, input().split())
tree = [[] for _ in range(N)]
happend = set()
for _ in range(M):
    a, b = map(lambda x: int(x)-1, input().split())
    if (a, b) not in happend and (b, a) not in happend:
        tree[a].append(b)
        tree[b].append(a)
        happend.add((a, b))
        happend.add((b, a))
visited = [False]*N
q = deque()
ans = 0
for i in range(N):
    if visited[i]:
        continue
    visited[i] = True
    q.append(i)
    tmp = 1
    while len(q):
        v = q.popleft()
        for e in tree[v]:
            
            if visited[e]:
                continue
            visited[e] += 1
            tmp += 1
            q.append(e)
            
    ans = max(tmp, ans)

print(ans)

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

Solution (Python):
from collections import deque
N,M = map(int,input().split())
l = [[] for _ in range(N+1)]

for _ in range(M):
  a,b = map(int,input().split())
  l[a].append(b)
  l[b].append(a)
ans = 1
check = [0]*(N+1)
for i in range(1,N+1):
  st = deque([i])
  check[i] = 1
  cnt = 1
  while st:
    s = st.popleft()
    for t in l[s]:
      if check[t] == 0:
        check[t] = 1
        st.append(t)
        cnt += 1
  ans = max(ans,cnt)
print(ans)

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

D = {}

parent = [-1] * N

visited = [False] * N

for root in range(N):
    if visited[root]:
        continue

    D[root] = set([root])
    
    stack = [root]
    
    while stack:
        
        n = stack.pop()
        
        visited[n] = True
        
        parent[n] = root

        
        for to in F[n]:
            if visited[to]:
                continue
            D[root].add(to)
            stack.append(to)
print(max(map(len,D.values())))

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        self.parents[x] += self.parents[y]
        self.parents[y] = x
    def size(self, x):
        return -self.parents[self.find(x)]
    def same(self, x, y):
        return self.find(x) == self.find(y)
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]
    def group_count(self):
        return len(self.roots())
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
    
N,M = map(int,input().split())
AB = [list(map(int,input().split())) for _ in range(M)]

uf = UnionFind(N)
for i in range(M):
    uf.union(AB[i][0]-1,AB[i][1]-1)
ufr = uf.roots()
ans = 0
for i in ufr:
    ans = max(ans,uf.size(i))
print(ans)

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

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

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

        if x == y: return

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

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

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

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

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

ans = 0
for c in UF.roots():
    ans = max(ans, UF.size(c))

print(ans)