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())
ab = [list(map(int, input().split())) for _ in range(m)]

class Union:
    def __init__(self, n):
        self.parents = [-1] * n
    
    def root(self, x):
        if self.parents[x] < 0:
            return x
        else:
            return self.root(self.parents[x])
    
    def unite(self, x, y):
        x = self.root(x)
        y = self.root(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

uni = Union(n)
for a, b in ab:
    uni.unite(a-1, b-1)
print(-min(uni.parents))

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

class UnionFind():
  def __init__(self, n):
    self.n = n
    self.parents = [-1]*n
  
  def find(self, x):
    if self.parents[x] < 0:
      return x
    else:
      self.parents[x] = self.find(self.parents[x])
      return self.parents[x]
    
  def union(self, x, y):
    x=self.find(x)
    y=self.find(y)
    
    if x== y:
      return
    
    if self.parents[x] > self.parents[y]:
      x, y = y, x
      
    self.parents[x] += self.parents[y]
    self.parents[y] = x
    
  def size(self, x):
    return -self.parents[self.find(x)]
  
uf = UnionFind(n)
ans=0

for i in range(m):
  a, b = map(int,input().split())
  a -= 1
  b -= 1
  uf.union(a, b)
  
for i in range(n):
  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 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())
ans = 0

UF = UnionFind(N)

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

for i in range(N):
    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)]


if __name__ == "__main__":
    N, M = map(int, input().split()) 
    union_find = UnionFind(N)
    for _ in range(M):
        A, B = map(int, input().split())
        A -= 1
        B -= 1
        union_find.union(A, B)

    answer = 0
    for i in range(N):
        answer = max(answer, union_find.size(i))

    print(answer)

Solution (Python):
class UF():
  def __init__(self, N):
    self._parent=[n for n in range(0, N)]
    self._size=[1] * N

  def find_root(self, x):
    if self._parent[x]==x:return x
    self._parent[x]=self.find_root(self._parent[x])
    return self._parent[x]

  def unite(self, x, y):
    gx=self.find_root(x)
    gy=self.find_root(y)
    if gx==gy:return

    if self._size[gx]<self._size[gy]:
      self._parent[gx]=gy
      self._size[gy]+=self._size[gx]
    else:
      self._parent[gy]=gx
      self._size[gx]+=self._size[gy]

  def size(self, x):
    return self._size[self.find_root(x)]

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

  def groupnum(self):
    N=len(self._parent)
    ans=0
    for i in range(N):
      if self.find_root(i)==i:
        ans+=1
    return ans

n,m=map(int,input().split())
UFa=UF(n)
for i in range(m):
  x,y=map(int,input().split())
  UFa.unite(x-1,y-1)
ans=[]
for i in range(n):
  ans.append(UFa.size(i))
print(max(ans))

Solution (Python):
from collections import defaultdict, deque
dic = defaultdict(list)
N, M  = map(int, input().split())
for i in range(M):
    a, b = map(int, input().split())
    dic[a].append(b)
    dic[b].append(a)
ans = 0
now = 1
seen = [-1]*N
queue = deque()

for i in range(N):
    if seen[i]!=-1:
        continue
    queue.append(i+1)
    seen[i]=now
    temp=0
    while queue:
        temp+=1
        q = queue.popleft()
        for j in dic[q]:
            if seen[j-1]!=-1:
                continue
            queue.append(j)
            seen[j-1]=now
    now+=1
    ans = max(ans, temp)

print(ans)

Solution (Python):


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

    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__':
    
    
    n, m = list(map(int, input().split()))     

    
    x = m
    abList = sorted([list(map(int, input().split())) for _ in range(x)])     

    
    uf = UnionFind(n)
    for i in range(m):
        uf.union(abList[i][0]-1, abList[i][1]-1)

    out = max(uf.size(r) for r in uf.roots())
    
    print("{}".format(out))

Solution (Python):


import sys
sys.setrecursionlimit(10**7)

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

visited=[0]*N
frnds=[[] for i in range(N)]

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

for i in range(N):
    frnds[i]=list(set(frnds[i]))

def saiki(num):
    value=1
    visited[num]=1
    for f in frnds[num]:
        if visited[f]!=1:
            value+=saiki(f)
    return value

ans=0
for i in range(N):
    if visited[i]!=1:
        ans=max(saiki(i),ans)

print(ans)

Solution (Python):
N,Q = map(int,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)]


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

M = 0 
for i in range(N):
    M = max(size(i),M)
print(M)

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

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

mp = [False]*n
mcnt = 0
for i in range(n):
    if mp[i]:
        continue
    queue = [i]
    cnt = 0
    mp[i] = True
    while(queue):
        num = queue.pop()
        cnt += 1
        target = set(l[num])
        for x in target:
            if mp[x]:
                continue
            mp[x]=True
            queue.append(x)
    mcnt = max(cnt,mcnt)

print(mcnt)

Solution (Python):

import base64
import subprocess
import zlib


exe_bin = "c$~dk4Rlo1wLW)dk_;i48

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

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

    def find(self, x):
        """
        要素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が属するグループと要素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):
        """
        要素xが属するグループのサイズ（要素数）を返す
        """
        return -self.parents[self.find(x)]

    def same(self, x, y):
        """
        要素x, yが同じグループに属するかどうかを返す
        """
        return self.find(x) == self.find(y)

    def members(self, x):
        """
        要素xが属するグループに属する要素をリストで返す
        """
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        """
        すべての根の要素をリストで返す
        """
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        """
        グループの数を返す
        """
        return len(self.roots())

    def all_group_members(self):
        """
        {ルート要素: [そのグループに含まれる要素のリスト], ...}の辞書を返す
        """
        return {r: self.members(r) for r in self.roots()}

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



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

    uf = UnionFind(N)
    for i in range(M):
        x = A_B[i][0] - 1
        y = A_B[i][1] - 1
        uf.union(x, y)

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

    print(ans)
    return


if __name__ == '__main__':
    main()

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

d = [-1]*N


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


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


for f in F:
    union(f[0]-1, f[1]-1)
print(-min(d))

Solution (Python):

import numpy
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)
answer = []
for i in range(n):
    answer.append(uf.size(i))
print(max(answer))

Solution (Python):
import sys

from collections import deque, Counter, defaultdict

import bisect
import heapq

import itertools
import numpy as np
input = sys.stdin.readline
sys.setrecursionlimit(10**8)
inf = 10**18
MOD = 1000000007
ri = lambda : int(input())
rs = lambda : input().strip()
rl = lambda : list(map(int, input().split()))

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

    
    def find(self, x):
        if(self.root[x] < 0):
            return x
        else:
            self.root[x] = self.find(self.root[x])
            return self.root[x]
    
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if(x == y):
            return 
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1
    
    def same(self, x, y):
        return self.find(x) == self.find(y)
    
    def size(self, x):
        return -self.root[self.find(x)]
n,m = rl()    
uf = UnionFind(n)
for i in range(m):
    a,b = rl()
    uf.unite(a,b)
print(-min(uf.root))

Solution (Python):
code = r"""

from libcpp cimport bool
from libcpp.vector cimport vector
cdef extern from "atcoder.hpp" namespace "atcoder":
    cdef cppclass dsu:
        dsu(int n)
        int merge(int a, int b)
        bool same(int a, int b)
        int leader(int a)
        int size(int a)
        vector[vector[int]] groups()
from libc.stdio cimport getchar, printf
cdef inline int read():
    cdef int b, c = 0
    while 1:
        b = getchar() - 48
        if b < 0: return c
        c = c * 10 + b
cdef int n = read(), m = read(), i, a, t
cdef dsu *d = new dsu(n)
for i in range(m): d.merge(read() - 1, read() - 1)
cdef vector[vector[int]] g = d.groups()
for i in range(g.size()):
    t = g[i].size()
    if t > a: a = t
printf('%d\n', a)
"""
import sys
if sys.argv[-1] == 'ONLINE_JUDGE':
    import os, zlib, base64
    open("atcoder.hpp","wb").write(zlib.decompress(base64.b85decode("c%1D$Yjfj9j^F(&dTJ|klq_jvd6L}vb(fiBvbjrkH*4pv>ReidmMEEHiqw*nEPKZH+YdlL*e^<y?b+l~Q6*!EjYgx<02+-(H~0P!r{iQfiP%Y)%(6T
    open('solve.pyx', 'w').write(code)
    os.system('cythonize -i -3 -b solve.pyx')
import solve

Solution (Python):
import sys
sys.setrecursionlimit(10000000)
N, M = map(int, input().split())
ki = [[] for _ in range(N)]
for _ in range(M):
    a, b = map(int, input().split())
    ki[a-1].append(b-1)
    ki[b-1].append(a-1)
tf = [False for _ in range(N)]


def dfs(v):
    global eda
    tf[v] = True
    eda += 1
    for nv in set(ki[v]):
        if not tf[nv]:
            dfs(nv)

ans = 0
for i in range(N):
    if not tf[i]:
        eda = 0
        dfs(i)
        ans = max(ans, eda)
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n+1)]
        self.rank = [0] * (n+1)
        self.size = [1] * (n+1)
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    def same_check(self, x, y):
        return self.find(x) == self.find(y)
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.size[y] += self.size[x]
        else:
            self.par[y] = x
            self.size[x] += self.size[y]
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

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

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

max = 1
for size in uf.size:
    if size > max:
        max = size

print(max)

Solution (Python):
import sys
import resource

def root(x):
  if par[x] == x:
    return x
  par[x] = root(par[x])
  return par[x]

def union(x, y):
  rx = root(x)
  ry = root(y)
  if rx != ry:
    par[rx] = ry
  return 0

sys.setrecursionlimit(10 ** 6)
n, m=map(int, input().split(" "))
par = list(range(n + 1))
for i in range(m):
  a, b = map(int, input().split(" "))
  union(a, b)

maxi = 0
count = 1

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

for i in range(1, n + 1):
  countpar[root(par[i])] += 1
print(max(countpar))

Solution (Python):
from networkx import *
print(max(*map(len,connected_components(Graph([*map(str.split,open(0))][1:]))),1,0))

Solution (Python):
"""
UnionFindにはいろいろな実装があるが, 本問ではparents配列にノード数を保持する実装だと非常に簡単に解ける. 
以下のようにしてノード数を保持する.
自身が子のとき, 親ノード番号を格納する.
自身が根のとき, ノード数を負の数で格納する.
つまり,　負の数のときは自身が根であり, その絶対値がその木のノード数を表す.
初期化時は、すべてのノードを−1で初期化する.
"""

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



par = [-1] * N  
rank = [0] * N 


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


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


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

for i in range(M):
    x,y = map(int,input().split())
    x -= 1; y -= 1
    unite(x,y)


ans = min(par)

print(abs(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)]


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

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

print(ans)

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

s = list()
"""

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


def find(x):

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

    return x


def union(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        return 0
    else:
        par[x] = y



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


for k in range(n):
    s.append(find(k))

c = collections.Counter(s)
print(max(c.values()))

Solution (Python):
n, m = map(int,input().split())
lst = [-1 for i in range(n + 1)]
lst[0] = 0
def find(x):
    if(lst[x] < 0):
        return(x)
    else:
        return(find(lst[x]))
def unit(x, y):
    xr = find(x)
    yr = find(y)
    if (xr == yr):
        pass
    else:
        if (xr > yr):
            x, y = y, x
            xr, yr = yr, xr
        lst[xr] = lst[xr] + lst[yr]
        lst[yr] = xr

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

print(-(min(lst)))

Solution (Python):
import collections

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

q = collections.deque()
visited = [0 for i in range(n)]

ans = 0
for i in range(n):
    tmp = 0
    if visited[i] == 0:
        visited[i] = 1
        tmp += 1
        for j in friend[i]:
            if visited[j] == 0:
                visited[j] = 1
                tmp += 1
                q.append(j)
        while q:
            s = q.pop()
            for k in friend[s]:
                if visited[k] == 0:
                    visited[k] = 1
                    tmp += 1
                    q.append(k)
    ans = max(ans,tmp)

print(max(ans,1))

Solution (Python):
from collections import deque
N, M = map(int, input().split())

graph = [[] for _ in range(N+1)]
for i in range(M):
    a, b = map(int, input().split(' '))
    graph[a].append(b)
    graph[b].append(a)
    
dist = [-1] * (N+1)
dist[0] = 0

disjoint_set = []
n_disj = 0
d = deque()

for j in range(1,N+1):
    if dist[j] != -1:
        continue
    
    dist[j] = 0
    d.append(j)
    disjoint_set.append([])
    disjoint_set[n_disj].append(j)
        
    while d:
        v = d.popleft()
        for i in graph[v]:
            if dist[i] != -1:
                continue
            dist[i] = dist[v] + 1
            d.append(i)
            disjoint_set[n_disj].append(i)

    n_disj+=1
    
ans = 1
for s in disjoint_set:
    ans = max(ans, len(s))
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 0
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        self.parents[x] += self.parents[y]
        self.parents[y] = x
        
N,M,*f = map(int, open(0).read().split())
AB = [f[i*2:i*2+2] for i in range(M)]
uf = UnionFind(N)
for A,B in AB:
    uf.union(A-1,B-1)
print(min(uf.parents)*(-1))

Solution (Python):



from math import gcd
from itertools import combinations,permutations,accumulate, product 

from collections import deque,defaultdict,Counter
import decimal
import re
import math
import bisect
import heapq














import sys
sys.setrecursionlimit(10000000)
mod = 10**9 + 7


INF = float('inf')
from sys import stdin
readline = stdin.readline
def readInts():
  return list(map(int,readline().split()))
def readTuples():
    return tuple(map(int,readline().split()))
def I():
    return int(readline())
class UnionFind:
    def __init__(self,n): 
        self.n = n
        self.parents = [-1] * n
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        self.parents[x] += self.parents[y]
        self.parents[y] = x
    def size(self, x):
        return -self.parents[self.find(x)]
n,m = readInts()
uni = UnionFind(n)
for i in range(m):
    a,b = map(lambda x:int(x)-1, input().split())
    uni.unite(a,b)
ans = -1
for i in range(n):
    ans = max(ans, uni.size(i)) 
print(ans)

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

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

tree = [-1] * N

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

def unite(x, y):
  rx, ry = root(x), root(y)
  if rx == ry: return
  tree[rx] += tree[ry]
  tree[ry] = rx

def size(x):
  return -tree[root(x)]

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

print(max(map(size, range(N))))

Solution (Python):
N,M = map(int,input().split())
A = [0]*M
B = [0]*M
for i in range(M):
    A[i],B[i] = 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 i in range(M):
    uf.union(A[i]-1,B[i]-1)

answer = 1
uflist = uf.parents
for i in range(N):
    time = uf.size(uflist[i])
    answer = max(time,answer)
print(answer)

Solution (Python):
import sys
if sys.argv[-1] == 'ONLINE_JUDGE':
    import os, zlib, base64
    open('solve.pyx', 'wb').write(zlib.decompress(base64.b85decode("c${TYO>cuR480@qAH2g<SksD5J4|Tok8~W85Fi=^lxC{7Uq74hU0=X{&(AMTO53&2Xd%xxXSJz7>bCE!gI2XS<-(vOg8X%LXU;vhylGT3lX}ZdrAE@IQs{2RE9GR(EkmL<t_%ZNs1oq^`kGMW(1(Ga6!i>F7X}`H7r5y^)s+
    os.system('cythonize -i -3 -b solve.pyx')
import solve

Solution (Python):
import sys
if sys.argv[-1] == 'ONLINE_JUDGE':
    import os, zlib, base64
    open('solve.pyx', 'wb').write(zlib.decompress(base64.b85decode("c${TYO>cuR480@qAH2g<SksD5J4|Tok8~W85Fi=^lxC{7Uq74hU0=X{&(AMTO53&2Xd%xxXSJz7>bCE!gI2XS<-(vOg8X%LXU;vhylGT3lX}ZdrAE@IQs{2RE9GR(EkmL<t_%ZNs1oq^`kGMW(1(Ga6!i>F7X}`H7r5y^)s+
    os.system('cythonize -i -3 -b solve.pyx')
import solve

Solution (Python):
import sys
if sys.argv[-1] == 'ONLINE_JUDGE':
    import os, zlib, base64
    open('solve.pyx', 'wb').write(zlib.decompress(base64.b85decode("c${TYO>cuR480@qAH2g<SksD5J4|Tok8~W85Fi=^lxC{7Uq74hU0=X{&(AMTO53&2Xd%xxXSJz7>bCE!gI2XS<-(vOg8X%LXU;vhylGT3lX}ZdrAE@IQs{2RE9GR(EkmL<t_%ZNs1oq^`kGMW(1(Ga6!i>F7X}`H7r5y^)s+
    os.system('cythonize -i -3 -b solve.pyx')
import solve

Solution (Python):
import sys
if sys.argv[-1] == 'ONLINE_JUDGE':
    import os, zlib, base64
    open('solve.pyx', 'wb').write(zlib.decompress(base64.b85decode("c${TYO>cuR480@qAH2g<SksD5J4|Tok8~W85Fi=^lxC{7Uq74hU0=X{&(AMTO53&2Xd%xxXSJz7>bCE!gI2XS<-(vOg8X%LXU;vhylGT3lX}ZdrAE@IQs{2RE9GR(EkmL<t_%ZNs1oq^`kGMW(1(Ga6!i>F7X}`H7r5y^)s+
    os.system('cythonize -i -3 -b solve.pyx')
import solve

Solution (Python):
import sys
if sys.argv[-1] == 'ONLINE_JUDGE':
    import os, zlib, base64
    open('solve.pyx', 'wb').write(zlib.decompress(base64.b85decode("c${TYO>cuR480@qAH2g<SksD5J4|Tok8~W85Fi=^lxC{7Uq74hU0=X{&(AMTO53&2Xd%xxXSJz7>bCE!gI2XS<-(vOg8X%LXU;vhylGT3lX}ZdrAE@IQs{2RE9GR(EkmL<t_%ZNs1oq^`kGMW(1(Ga6!i>F7X}`H7r5y^)s+
    os.system('cythonize -i -3 -b solve.pyx')
import solve

Solution (Python):


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

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

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

    def unite(self, x, y): 
        rx = self.root(x)
        ry = self.root(y)
        if rx == ry: 
            return

        

        
        if self.rank[rx] < self.rank[ry]:
            self.par[rx] = ry
            self.sizes[ry] += self.sizes[rx]
        else:
            self.par[ry] = rx
            self.sizes[rx] += self.sizes[ry]

        
        if self.rank[rx] == self.rank[ry]:
            self.rank[rx] += 1

    def size(self, x): 
        '''
        xが属するグループのサイズを返す
        (連結成分の大きさ)
        '''
        return self.sizes[self.root(x)]


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

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

print(ans)

Solution (Python):
l=lambda:map(int, input().split())
n,m=l()
p=[-1]*n
def root(x):
  if p[x]<0:return x
  p[x]=root(p[x]);return p[x]
def union(x,y):
  x,y=root(x),root(y)
  if x==y: return
  p[x]+=p[y]
  p[y]=x
def same(x,y):
  return root(x)==root(y)
def size(x):
  return -p[r(x)]
for _ in range(m):
  a,b=l()
  union(a-1,b-1)
print(-min(p))

Solution (Python):
import sys
from collections import Counter


inint = lambda: int(sys.stdin.readline())
inintm = lambda: map(int, sys.stdin.readline().split())
inintl = lambda: list(inintm())
instrm = lambda: map(str, sys.stdin.readline().split())
instrl = lambda: list(instrm())

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

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

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

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

    def roots(self):
        return {i for i, num in enumerate(self.root) if i == num}

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

n, m = inintm()

uf = UnionFind(n)

for i in range(m):
    a, b = inintm()
    uf.unite(a-1, b-1)

ans = 0

r = uf.roots()

for i in r:
    if uf.size(i) > ans:
        ans = uf.size(i)

print(ans)