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):
import sys
sys.setrecursionlimit(10**7)

N,Q = map(int,input().split())
class UF():
  def __init__(self,par,rank):
    self.par = par
    self.rank = rank
  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(self,x,y):
      return self.find(x) == self.find(y)
  def unite(self,x,y):
      x = self.find(x)
      y = self.find(y)
      if x == y:
          return 0
      if self.rank[x] < self.rank[y]:
          self.par[x] = y
      else:
          self.par[y] = x
          if self.rank[x]==self.rank[y]:self.rank[x]+=1
uf=UF([i for i in range(N)],[0]*(N+1))
for _ in range(Q):
  a,b=map(int,input().split())
  a,b=a-1,b-1
  uf.unite(a,b)
from collections import Counter
a=[-1]*N
for i in range(N):
  a[i]=uf.find(i)
ca=Counter(a)
ans=0
for c in ca.values():
  ans=max(ans,c)
print(ans)

Solution (Python):
import collections
def BFS(graph,start,reached):
    res = 0
    next = []
    if reached[start] == 1:
        return res
    reached[start] = 1
    res += 1
    next += list(graph[start])
    while len(next):
        tmp = next.pop()
        if reached[tmp] == 1:
            continue
        res += 1
        reached[tmp] = 1
        next += list(graph[tmp])
    return res

[n,m] = [int(i) for i in input().split()]
dic = collections.defaultdict(set)
ls = [0] * n
for i in range(m):
    [a,b] = [int(j)-1 for j in input().split()]
    dic[a].add(b)
    dic[b].add(a)
ans = 0
for i in range(n):
    ans = max(ans,BFS(dic,i,ls))
print(ans)

Solution (Python):


N, M = [int(x) for x in input().split(' ')]









class UF:
    def __init__(self):
        self.r = [-1] * N

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

    def union(self, i, j):
        i -= 1
        j -= 1
        ri = self.root(i)
        rj = self.root(j)
        if ri == rj:
            return
        else:
            if not self.r[ri] < self.r[rj]:
                ri, rj = rj, ri
            self.r[ri] += self.r[rj]
            self.r[rj] = ri
            return

    def max_size(self):
        return -min(self.r)

uf = UF()
for i in range(M):
    uf.union(*[int(x) for x in input().split(' ')])
print(uf.max_size())

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

  def get_root(self, i):
    while self.parent[i] != -1:
      i = self.parent[i]
    return i

  def is_same_tree(self, i, j):
    return self.get_root(i) == self.get_root(j)

  def merge(self, i, j):
    i = self.get_root(i)
    j = self.get_root(j)
    if i == j:
      return

    if self.rank[i] > self.rank[j]:
      self.parent[j] = i
      self.rank[i] = max(self.rank[i], self.rank[j] + 1)
      self.count[i] += self.count[j]
    else:
      self.parent[i] = j
      self.rank[j] = max(self.rank[j], self.rank[i] + 1)
      self.count[j] += self.count[i]


n, m = map(int, input().split())
uf = UnionFind(n)
for _ in range(m):
  a, b = [int(i) - 1 for i in input().split()]
  uf.merge(a, b)
print(max(uf.count))

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.parent = [-1] * n
        self.rank = [1] * n
        self.count = [1] * n
 
    def get_root(self, i):
        while self.parent[i] != -1:
            i = self.parent[i]
        return i
 
    def is_same_tree(self, i, j):
        return self.get_root(i) == self.get_root(j)
 
    def merge(self, i, j):
        i = self.get_root(i)
        j = self.get_root(j)
        if i == j:
            return
 
        if self.rank[i] > self.rank[j]:
            self.parent[j] = i
            self.rank[i] = max(self.rank[i], self.rank[j] + 1)
            self.count[i] += self.count[j]
        else:
            self.parent[i] = j
            self.rank[j] = max(self.rank[j], self.rank[i] + 1)
            self.count[j] += self.count[i]
n, m = map(int, input().split())
uf = UnionFind(n)
for _ in range(m):
  a, b = [int(i) - 1 for i in input().split()]
  uf.merge(a, b)
print(max(uf.count))

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


import sys
sys.setrecursionlimit(10**7)

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):
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):
import sys


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


if __name__ == "__main__":
    input = sys.stdin.readline
    n, m = map(int, input().split())
    par = [-1] * n
    s = set()
    for _ in range(m):
        a, b = map(int, input().split())
        if a > b:
            a, b = b, a
        s.add((a, b))

    for x, y in s:
        unite(x - 1, y - 1)

    print(-min(par))

Solution (Python):
n, m = map(int, input().split())
li=[-1]*n

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


def unite(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        return 0
    else:
        li[x] += li[y]
        li[y] = x


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


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

ans=0
for i in range(n):
    ans = max(ans,-li[i])

print(ans)

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

class UnionFind:
    
    def __init__(self, N):
        
        self.parent = [i for i in range(N)]
        self.rank = [0] * N
        self.count = 0

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

    
    def is_same(self, a, b):
        return self.root(a) == self.root(b)

    
    def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        
        if ra == rb: return
        
        
        if self.rank[ra] < self.rank[rb]:
            self.parent[ra] = rb
        else:
            self.parent[rb] = ra
            if self.rank[ra] == self.rank[rb]: self.rank[ra] += 1
        self.count += 1


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

for i in range(n):
    uf.root(i)
tmp = sorted(Counter(uf.parent).items(), key=lambda x:x[1])
print(tmp[-1][1])

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

class Union_Find():
    def __init__(self, n):
        """
        要素数n
        """
        self.n = n
        self.par = [-1] * n

    def find(self, x):
        """
        要素xが属するグループの根を返す
        return int
        """
        if self.par[x] < 0:
            return x

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

    def union(self, x, y):
        """
        要素xが属するグループと要素yが属するグループを併合する
        return null
        """
        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):
        """
        要素xが属するグループの要素数を取得する
        return int
        """
        return - self.par[self.find(x)]
        
    def same(self, x, y):
        """
        要素xと要素yが同じグループに属するかどうかを返す
        return bool
        """
        return self.find(x) == self.find(y)

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

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

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

    def all_group_members(self):
        """
        全てのグループに対してそれぞれ属する要素を返す
        return dict[array]
        """
        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 = Union_Find(N)

for a, b in AB:
    UF.union(a-1, b-1)

ans = 0

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

print(ans)

Solution (Python):
import bisect, copy, heapq, math, sys
from collections import *
from functools import lru_cache
from itertools import accumulate, combinations, permutations, product
def input():
    return sys.stdin.readline()[:-1]
def ruiseki(lst):
    return [0]+list(accumulate(lst))
def celi(a,b):
    return -(-a//b)
sys.setrecursionlimit(5000000)
mod=pow(10,9)+7
al=[chr(ord('a') + i) for i in range(26)]
direction=[[1,0],[0,1],[-1,0],[0,-1]]

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

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

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

    def union(self, x, y, w=1):
        rx = self.find(x)
        ry = self.find(y)
        if self.rank[rx] < self.rank[ry]:
            self.sizes[ry] += self.size(rx)
            self.par[rx] = ry
            self.weight[rx] = w - self.weight[x] + self.weight[y]
        else:
            self.sizes[rx] += self.size(ry)
            self.par[ry] = rx
            self.weight[ry] = -w - self.weight[y] + self.weight[x]
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1

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

    def diff(self, x, y):
        return self.weight[x] - self.weight[y]

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

uf=WeightedUnionFind(n)
for a,b in ab:
    uf.union(a,b)


dic={}
for i in range(n):
    pa=uf.find(i+1)
    if pa in dic:
        dic[pa]+=1
    else:
        dic[pa]=1

ans=0
for i in dic.values():
    ans=max(ans,i)
print(ans)

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

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

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

        x = self.Find_Root(x)
        y = self.Find_Root(y)
        if(x == y):
            return 

        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x
        else:
            self.root[y] += self.root[x]
            self.root[x] = y

            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1
    
    def Output(self):
        return [i for i in self.root if i < 0]

uf = UnionFind(n)
for i in ab:
    uf.Unite(i[0],i[1])

a = [-1 * i for i in uf.Output()]
del a[0]
print(max(a))

Solution (Python):

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


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

    if x == y:
        return False
    else:
        if par[x] > par[y]:
            x, y = y, x
        par[x] += par[y]
        par[y] = x
        return True


import sys

input = sys.stdin.readline
n, m = map(int, input().split())
par = [-1] * n
a = set()
for _ in range(m):
    ab = sorted(map(int, input().split()))
    a.add((ab[0], ab[1]))

for x, y in a:
    unite(x - 1, y - 1)

print(-min(par))

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())
union = UnionFind(N)

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

print(-min(union.parents))

Solution (Python):
from collections import deque

n, m = map(int, input().split())
l = [[] for i in range(n)]
union = []
vis = [-1]*n
ans = 0

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

q = deque()

for i in range(n):
    temp = []
    q.append(i)
    while q:
        a = q.popleft()
        if vis[a] == -1:
            vis[a] = 0
            temp.append(a)
            for j in l[a]:
                q.append(j)
    if len(temp) > 0:
        union.append(temp)


for i in union:
    ans = max(ans, len(i))

print(ans)

Solution (Python):
from collections import deque
N,M=map(int,input().strip().split())
l=list()
dp=[list() for _ in range(N)]
id=[-1 for _ in range(N)] 
for _ in range(M):
    a,b=map(int,input().strip().split())
    l.append((a,b))
    dp[a-1].append(b)
    dp[b-1].append(a)
    id[a-1]=0
    id[b-1]=0

i=1
c=[]
for n in range(1,N+1):
    cnt=0
    if id[n-1]==0:
        q=deque([n])
        while q:
            tmp=q.popleft()
            cnt+=1
            id[tmp-1]=i
            for e in dp[tmp-1]:
                if id[e-1]==0:
                    id[e-1]=i
                    q.append(e)
                else:
                    continue
        i+=1
        c.append(cnt)
    else:
        continue
if c:
    print(max(c))
else:
    print(1)

Solution (Python):
import queue

class graph:
    def __init__(self, n):
        self.node = [[] for _ in range(n)]
        self.unexplored = [True for _ in range(n)]
        self.link = []
    
    def unit(self, a, b):
        self.node[a].append(b)
        self.node[b].append(a)
    
    def get_node(self):
        return self.node

    def bfs(self, start, idx):
        self.unexplored[start] = False
        self.link[idx].append(start)
        d = queue.deque()
        d.extend(self.node[start])
        while d:
            vis = d.popleft()
            if self.unexplored[vis]:
                self.link[idx].append(vis)
                self.unexplored[vis] = False
                d.extend(self.node[vis])
    
    def split_link(self):
        idx = 0
        for i in range(len(self.node)):
            if self.unexplored[i]:
                self.link.append([])
                self.bfs(i, idx)
                idx += 1

    def get_linklen(self):
        return [len(x) for x in self.link]

n, m = map(int, input().split())
g = graph(n)
for _ in range(m):
    a, b = map(int, input().split())
    g.unit(a-1, b-1)

g.split_link()
print(max(g.get_linklen()))

Solution (Python):






































class UnionFind():
    def __init__(self, n):
        self.parents = [-1]*n 
    
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]
    
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y) 
        if x==y:
            return
        
        if self.parents[x] > self.parents[y]:
            x,y = y,x
        
        self.parents[x] += self.parents[y]
        self.parents[y] = x
    
    def size(self,x):
        return -self.parents[self.find(x)]
    
def main():
    n,m = map(int,input().split())
    uf = UnionFind(n)
    for _ in range(m):
        a, b = map(int, input().split())
        uf.union(a-1,b-1)
    
    ans = 1
    for i in range(n):
        ans = max(ans, uf.size(i))
    print(ans)

if __name__ == "__main__":
    main()

Solution (Python):
import sys
input = sys.stdin.readline
from collections import Counter


def read():
    N, M = list(map(int, input().strip().split()))
    AB = []
    for i in range(M):
        a, b = map(int, input().strip().split())
        AB.append((a, b))
    return N, M, AB


class UnionFind():
    """Union-Find木の実装
    """

    def __init__(self, n):
        self.n = n
        self.parent = [x for x in range(n)]

    def find(self, x):
        """要素xが所属するグループを返す
        """
        if self.parent[x] == x:
            return x
        else:
            self.parent[x] = self.find(self.parent[x])
            return self.parent[x]

    def union(self, x, y):
        """要素x, yがそれぞれ所属するグループを併合する
        """
        x = self.find(x)
        y = self.find(y)
        if x > y:
            x, y = y, x
        self.parent[y] = x

    def parents(self):
        """全てのノードについて、対応する親ノードを返す"""
        return [self.find(x) for x in range(self.n)]


def solve(N, M, AB):
    uf = UnionFind(N)
    for a, b in AB:
        uf.union(a-1, b-1)
    C = Counter(uf.parents())
    return C.most_common()[0][1]


if __name__ == '__main__':
    inputs = read()
    outputs = solve(*inputs)
    if outputs is not None:
        print("%s" % str(outputs))

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

root = [-1]*n
def r(x):
    if root[x] < 0: 
        return x
    else:
        root[x] = r(root[x])
        return root[x]

def unite(x, y):
    x = r(x)
    y = r(y)
    if x == y:
        return
    root[x] += root[y]
    root[y] = x 

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

ans = 0
for i in range(n):
    ans = max(ans, -root[i])

print(ans)

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

root = [-1]*n
def r(x):
    if root[x] < 0: 
        return x
    else:
        root[x] = r(root[x])
        return root[x]

def unite(x, y):
    x = r(x)
    y = r(y)
    if x == y:
        return
    root[x] += root[y]
    root[y] = x 

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

ans = 0
for i in range(n):
    ans = max(ans, -root[i])

print(ans)

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

root = [-1]*n
def r(x):
    if root[x] < 0:
        return x
    else:
        root[x] = r(root[x])
        return root[x]

def unite(x, y):
    x = r(x)
    y = r(y)
    if x == y:
        return
    root[x] += root[y]
    root[y] = x

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

ans = 0
for i in range(n):
    ans = max(ans, -root[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とyは-=1して使う
        '''
        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 UnionFind:
    def __init__(self, n):
        self.p = [i for i in range(n)]
        self.size = [1 for i in range(N)]
        self.components = n  

    def root(self, x):
        if self.p[x] == x:
            return x
        else:
            self.p[x] = self.root(self.p[x])
            return self.p[x]
    
    def unite(self, x, y):
        x, y = self.root(x), self.root(y)
        if x != y:
            self.p[x] = y
            self.components -= 1
            self.size[y] = self.size[x] + self.size[y] 

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

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

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

print(max(UF.size))

Solution (Python):
from collections import defaultdict
import sys
sys.setrecursionlimit(1 << 25)  

G = defaultdict(lambda: [])


N,M = map(int,input().split())
color = {key:0 for key in range(N)}

for _ in range(M):
    s,t = map(int,input().split())
    G[s-1].append(t-1)
    G[t-1].append(s-1)


def dfs(node:int, co:int):
    
    if color[node] != 0:
        return
    
    color[node] = co
    for n in G[node]:
        dfs(n,co)

    return


c = 1
for node in G.keys():
    dfs(node,c)
    c += 1

ans_list = [0]*(N)
for i in range(N):
    ans_list[color[i]] += 1

ans_list[0] = 0
if M == 0:
    print(1)
else:
    print(max(ans_list))

Solution (Python):
import sys
sys.setrecursionlimit(1000000)

def DFS(i):
    if done[i]:
        ans[-1]+=1
        done[i]=False
        for g in G[i]:
            if done[g]:
                DFS(g)
    else:
        return p

N,M=map(int,input().split())
G=[[] for _ in range(N)]
done=[True for _ in range(N)]

for i in range(M):
    a,b=map(int,input().split())
    a-=1
    b-=1
    G[a].append(b)
    G[b].append(a)
ans=[]
for j in range(N):
    ans.append(0)
    if done[j]:
        DFS(j)
print(max(ans))

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

readline = sys.stdin.buffer.readline
def readstr():return readline().rstrip().decode()
def readstrs():return list(readline().decode().split())
def readint():return int(readline())
def readints():return list(map(int,readline().split()))
def printrows(x):print('\n'.join(map(str,x)))
def printline(x):print(' '.join(map(str,x)))

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

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

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


n,m = readints()
u = UnionFind(n)
for i in range(m):
    a,b = (x-1 for x in readints())
    u.unite(a,b)

print(max([u.size(x) for x in range(n)]))

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

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

root = [-1]*n

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

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

def size(x):
    x = find(x)
    return -root[x]

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

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

print(ans)

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

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

n,m = map(int,input().split())
par = [-1]*n
line = [0 for i in range(n)]
ans = 0
for i in range(m):
  a,b = map(int, input().split())
  unite(a-1,b-1)
for i in range(n):
  line[find(i)] += 1
  if line[find(i)] > ans:
    ans = line[find(i)]
print(ans)

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

n, m = map(int, input().split())
root = [-1] * n

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

def unite(x, y):
    x = find_root(x)  
    y = find_root(y)
    if x == y:
        return
    root[x] += root[y]
    root[y] = x

def size(x):
    x = find_root(x)
    return -root[x]

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

max_size = max(map(size, range(n)))

print(max_size)

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())
    a-=1
    b-=1
    uf.union(a, b)

ans =0
a = uf.roots()
for i in range(len(a)):
    if uf.size(a[i])>ans:
        ans = uf.size(a[i])
print(ans)

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.parents = [-1 for _ 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 union(self, x, y):  
        x_root = self.find(x)  
        y_root = self.find(y)  

        if x_root == y_root:  
            return

        if abs(self.parents[x_root]) >= abs(self.parents[y_root]):  
            self.parents[x_root] += self.parents[y_root]
            self.parents[y_root] = x_root
        else:
            self.parents[y_root] += self.parents[x_root]
            self.parents[x_root] = y_root

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


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

    for _ 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)


if __name__ == "__main__":
    main()

Solution (Python):
from collections import deque

N,M = map(int,input().split())
A = [[] for i in range(N)]
checkd = [False]*N
for _ in range(M):
    a,b = (map(lambda a: int(a)-1, input().split()))
    A[a].append(b)
    A[b].append(a)
nextS = set(range(N))
ans = 0
while len(nextS)>0:
    s = nextS.pop()
    if checkd[s]: 
        continue
    count = 0
    que = deque([s])
    while len(que)>0:
        nn = que.popleft()
        if checkd[nn]:
            continue
        checkd[nn] = True
        nextS.discard(nn)
        count += 1
        que.extend(A[nn])
    ans = max(count,ans)


print(ans)