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**9)
 
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
 
 
def size(x):
    return -1 * root[r(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):
import sys
sys.setrecursionlimit(int(1e6))

def search(x, num):
    nodes.remove(x)
    for y in edge[x]:
        edge[y].discard(x)
    for y in list(edge[x]):
        if y in nodes:
            num = search(y, num)
    return num + 1

(n,m),*d  = [list(map(int, s.split())) for s in open(0)]

edge = [set() for _ in range(n+1)]
for x in d:
    edge[x[0]].add(x[1])
    edge[x[1]].add(x[0])

nodes = set(range(1,n+1))
ans = 1
for x in list(nodes):
    if x in nodes:
        ans = max(ans, search(x, 0))
print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(int(1e6))

def search(x, num):
    nodes.remove(x)



    for y in edge[x]:
        if y in nodes:
            num = search(y, num)
    return num + 1

(n,m),*d  = [list(map(int, s.split())) for s in open(0)]

edge = [set() for _ in range(n+1)]
for x in d:
    edge[x[0]].add(x[1])
    edge[x[1]].add(x[0])

nodes = set(range(1,n+1))
ans = 1
for x in list(nodes):
    if x in nodes:
        ans = max(ans, search(x, 0))
print(ans)

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

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

lis = [[] for _ in range(N+1)]
for i in range(M):
    A,B = map(int,input().split())
    lis[A].append(B)
    lis[B].append(A)
    
cnt = 0
seen = [False]*(N+1)
def dfs(v,graph):
    global cnt
    seen[v] = True
    for next_v in graph[v]:
        if seen[next_v] == True:
             continue
        if seen[next_v] == []:
             continue
        cnt += 1
        dfs(next_v,graph)
    return cnt

ma = 0
for j in range(N):
    cnt = 0
    if seen[j] == True:
        continue
    ma = max(ma,dfs(j,lis))
print(ma+1)

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

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

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(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

    def size(self, x):
        return -self.parents[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):
    ans = max(ans, uf.size(i))

print(str(ans))

Solution (Python):
import sys
input = sys.stdin.readline
INF = 10**18
sys.setrecursionlimit(10**6)

def li():
    return [int(x) for x in 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):
        root = self.find(x)
        return -self.parents[root]

    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 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 = li()
uf = UnionFind(N)
for i in range(M):
    a, b = li()
    uf.union(a-1, b-1)

ans = max(uf.size(x) for x in range(N))
print(ans)

Solution (Python):
import queue
import sys
sys.setrecursionlimit(10**6)

n, m = map(int, input().split())
readline = sys.stdin.readline


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

    def find(self, x):
        """
        根のIDを返す
        """
        if self.d[x] < 0:
            return x  
        
        self.d[x] = self.find(self.d[x])
        return self.d[x]

    def unite(self, x, y):
        """
        根同士をくっつける
        """
        x = self.find(x)
        y = self.find(y)  
        if x == y:
            return False  
        if self.d[x] > self.d[y]:
            x, y = y, x  
        self.d[x] += self.d[y]  
        self.d[y] = x  
        return True

    def same(self, x, y):
        """
        同じ集合に所属しているかどうか
        """
        return self.find(x) == self.find(y)

    def size(self, x):
        """
        連結成分サイズを返す
        """
        return -self.d[self.find(x)]


uf = UnionFind(n)

for _ in range(m):
    a, b = [int(i) for i in readline().split()]
    a -= 1
    b -= 1
    uf.unite(a, b)

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

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)

lsloop = []
used = [False for i in range(n+1)]

for j in range(1,n+1):
    if used[j]:
        continue        
    ii = 1
    d = deque()
    d.append(j)
    used[j] = True
    while d:
        v = d.popleft()
        for i in graph[v]:
            if used[i]:
                continue
            ii += 1
            d.append(i)
            used[i] = True
    lsloop.append(ii)
print(max(lsloop))

Solution (Python):
from collections import deque

N, M = map(int, input().split())
rinsetu = [set() for _ in range(N + 1)]
for i in range(M):
    a, b = map(int, (input().split()))
    rinsetu[a].add(b)
    rinsetu[b].add(a)

grp = 0
color = ["white"] * (N + 1)
color_2 = ["white"] * (N + 1)
color[0] = "black"
for i in range(1, N + 1):
    count=1
    if color[i] == "white":
        d = deque()
        d.append(i)
        a = set()
        a.add(i)
        while (d):
            k = d.popleft()
            color[k] = "black"
            color_2[k]="black"
            for j in rinsetu[k]:
                if color[j] == "white" and color_2[j]=="white":
                    color_2[j]="black"
                    d.append(j)
                    count+=1
        grp=max(grp,count)
print(grp)

Solution (Python):
class UFTree():
  def __init__(self,n):
    self.N = n
    self.parents = [-1]*n
    
  def root(self,n):
    if self.parents[n]<0: return n
    else:
      self.parents[n] = self.root(self.parents[n])
      return self.parents[n]
      
  def unite(self,x,y):
    rx,ry = self.root(x), self.root(y)
    if rx==ry: return
    if rx>ry: rx,ry = ry,rx
    self.parents[rx] += self.parents[ry]
    self.parents[ry] = rx
      
  def size(self,x):
    return -self.parents[self.root(x)]
  
N,M = map(int,input().split())
uft = UFTree(N)
for i in range(M):
  A,B = map(int,input().split())
  uft.unite(A-1,B-1)
print(max([uft.size(i) for i in range(N)]))

Solution (Python):


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

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

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

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

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

    
    
    par = [-1]*n
    
    for i in range(m):
        A,B = map(int, input().split())
        unite(A-1,B-1)
    print(max([size(i) for i in range(n)]))


if __name__ == '__main__':
    main()

Solution (Python):
import sys


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

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

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

        if x == y:
            return

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

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


N, M = map(int, input().split())
info = [tuple(map(int, s.split())) for s in sys.stdin.readlines()]

uf = UnionFind(N)
for a, b in info:
    a -= 1; b -= 1
    uf.union(a, b)

ans = min(uf.parents)

print(-ans)

Solution (Python):

import sys
sys.setrecursionlimit(10**6)
INF = 10 ** 9 + 1  
MOD = 10 ** 9 + 7


def debug(*x):
    print(*x, file=sys.stderr)


def find_root(x):
    p = parent[x]
    if p == -1:
        return x
    p2 = find_root(p)
    parent[x] = p2
    return p2


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


def is_connected(x, y):
    return (find_root(x) == find_root(y))


def solve(SOLVE_PARAMS):
    pass


def main():
    global parent, rank
    
    N, M = map(int, input().split())
    parent = [-1] * N
    rank = [0] * N
    for q in range(M):
        a, b = map(int, input().split())
        unite(a - 1, b - 1)

    xs = list(find_root(x) for x in range(N))
    
    
    from collections import Counter
    print(max(Counter(xs).values()))



T1 = """
5 3
1 2
3 4
5 1
"""
TEST_T1 = """
>>> as_input(T1)
>>> main()
3
"""

T2 = """
4 10
1 2
2 1
1 2
2 1
1 2
1 3
1 4
2 3
2 4
3 4
"""
TEST_T2 = """
>>> as_input(T2)
>>> main()
4
"""

T3 = """
10 4
3 1
4 1
5 9
2 6
"""
TEST_T3 = """
>>> as_input(T3)
>>> main()
3
"""


def _test():
    import doctest
    doctest.testmod()
    g = globals()
    for k in sorted(g):
        if k.startswith("TEST_"):
            doctest.run_docstring_examples(g[k], g, name=k)


def as_input(s):
    "use in test, use given string as input file"
    import io
    f = io.StringIO(s.strip())
    g = globals()
    g["input"] = lambda: bytes(f.readline(), "ascii")
    g["read"] = lambda: bytes(f.read(), "ascii")


input = sys.stdin.buffer.readline
read = sys.stdin.buffer.read

if sys.argv[-1] == "-t":
    print("testing")
    _test()
    sys.exit()

main()

Solution (Python):
import sys
sys.setrecursionlimit(500*500)

N, M = map(int, input().split())
UF = [-1] * (N+1)
def find(x):
    global UF
    if UF[x] == -1:
        return x
    else:
        UF[x] = find(UF[x])
        return UF[x]
def union(x,y):
    global UF
    xx = find(x)
    yy = find(y)
    if UF[x] == UF[y] == -1:
        UF[y] = xx
        return
    elif xx == yy:
        return 
    else:
        UF[yy] = xx
        return 
    
for _ in range(M):
    x, y = map(int, input().split())
    union(x,y)
    
cnt = [0] * (N+1)
for i in range(1,N+1):
    z = find(i)
    cnt[z] += 1

print(max(cnt))

Solution (Python):
import sys

class UnionFind():
    def __init__(self,n):
        self.n = n
        self.parents=[-1 for _ in range(n)]
    
    def find(self,n):
        x=self.parents[n]
        if x<0:
            return n
        else:
            self.parents[n]=self.find(self.parents[n])
            return self.parents[n]
    
    def union(self,n,m):
        x=self.find(n)
        y=self.find(m)
        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

sys.setrecursionlimit(10**9)    
n,m=map(int,input().split())
uf=UnionFind(n)

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

ans=0

for p in uf.parents:
    ans=min(ans,p)

print(abs(ans))

Solution (Python):
class union_find:
  def __init__(self, n):
    self.par = [i for i in range(n)]
    self.rank = [0 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.par[x] == self.par[y]
        
  def unite(self, x, y):
    x, y = self.root(x), self.root(y)
    if x != y:
      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

N, M = map(int, input().split())
uf = union_find(N)
for i in range(M):
  a, b = map(int, input().split())
  uf.unite(a-1, b-1)
for i in range(N):
  uf.par[i] = uf.root(i)
D = {}
L = [uf.par[i] for i in range(N)]
for i in range(N):
  if L[i] in D:
    D[L[i]] += 1
  else:
    D[L[i]] = 1
print(max(D[i] for i in D))

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

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


def size(x):
    return -1 * root[r(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):
class UnionFind:
    def __init__(self, n=1):
        self.parent = [i for i in range(n)]
        self.rank = [0] * n
    
    def find(self, x):
        if self.parent[x] == x:
            return x
        else:
            self.parent[x] = self.find(self.parent[x])
            return self.parent[x]
    
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            if self.rank[x] < self.rank[y]:
                x, y = y, x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.parent[y] = x
    
    def is_same(self, x, y):
        return self.find(x) == self.find(y)


from collections import Counter
N, M = map(int, input().split())
uf = UnionFind(N)
s = set()
for i in range(M):
    a, b = sorted(map(int, input().split()))
    a -= 1; b -= 1
    if (a, b) in s:
        continue
    s.add((a, b))
    uf.union(a, b)

for i in range(N):
    uf.find(i)

g = [uf.find(i) for i in range(N)]
ans = max(Counter(g).values())
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
        
def size(x):
    return -par[find(x)]
    
n,m = map(int,input().split())

l =[[] for _ in range(n)]
par = [-1]*n

for i in range(m):
    a,b = map(int,input().split())
    l[a-1].append(b-1)
    l[b-1].append(a-1)
    unite(a-1,b-1)
    
ans = 0    
for i in range(n):
    ans = max(ans,size(i))
    
print(ans)

Solution (Python):
import numpy as np

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


par = [i for i in range(N+1)] 
size = [1 for _ in range(N+1)] 

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

for AB in ABs:
    unite(AB[0],AB[1])

print(max(size))

Solution (Python):
n, m = map(int, input().split())
groups = [x for x in range(n)]
count = [0]*n

def UnionFind(x):
    a = x
    while a != groups[a]:
        a = groups[a]
    groups[x] = a
    return a

for _ in range(m):
    x, y = map(int, input().split())
    x, y = UnionFind(x-1), UnionFind(y-1)
    if x != y:
        groups[y] = x
    
for i in range(n):
    count[UnionFind(i)] += 1
print(max(count))

Solution (Python):
from collections import deque
n,m=map(int,input().split())
seen=[False]*n
num=[[] for _ in range(n)]
for i in range(m):
    a,b=map(int,input().split())
    num[a-1].append(b)
    num[b-1].append(a)
ans=0
for i in range(n):
    if seen[i]==False:
        queue=deque()
        queue.append(i)
        cnt=1
        yn=0
        while yn!=1:
            if len(queue)!=0:
                num01=queue.popleft()
            else:
                yn=1
            seen[num01]=True
            for j in range(len(num[num01])):
                num10=num[num01][j]-1
                if seen[num10]==False:
                    seen[num10]=True
                    cnt+=1
                    queue.append(num10)
        ans=max(ans,cnt)
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 _ 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):
        """
        要素xのrootを見つける
        """
        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,要素yについて
        rootが同じ場合そのまま
        異なる場合は要素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のrootが同じか返す
        """
        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 __str__(self):
        return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))



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

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

for a, b in A_B:
    union.unite(a-1, b-1)
ans = 0
for i in range(N):
    ans = max(ans, union.size(i))
print(ans)

Solution (Python):
import sys


def main():

    input = sys.stdin.readline

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

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

    UF = UnionFind(N)

    for i in range(M):
        A,B = AB[i]

        A = A - 1
        B = B - 1

        UF.union(A,B)


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

    print(ans)

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n
        
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]
    
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        
        if x == y:
            return
        
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        
        self.parents[x] += self.parents[y]
        self.parents[y] = x
    
    def size(self, x):
        return -self.parents[self.find(x)]
        
    def same(self, x, y):
        return self.find(x) == self.find(y)
    
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
    
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

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

if __name__ == "__main__":
    main()

Solution (Python):
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())
    s = [j for j in range(n)]
    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(uf.size(i),ans)
    print(ans)
resolve()

Solution (Python):
import sys

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

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

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

        if x == y:
            return

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

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

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

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

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

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

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

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

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

input = sys.stdin.readline

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

uf = UnionFind(N)
for a, b in relations:
    uf.union(a, b)

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

  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())
friends = UnionFind(N)
for _ in range(M):
  A, B = map(int, input().split())
  A -= 1
  B -= 1
  friends.union(A, B)
x = friends.roots()
ans = 0
for k in x:
  y = friends.size(k)
  ans = max(ans,y)
print(ans)

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

if m != 0:
  g = [set() for _ in range(n)]
  valid = [-1] * n
  set_list = []
  for _ in range(m):
    a, b = [int(x) for x in input().split()]
    g[a-1].add(b-1)
    g[b-1].add(a-1)

  j = -1
  for i in range(n):
    if valid[i] == -1:
      set_list.append(set())
      j += 1
      stack = [i]
      while len(stack)!=0:
        v = stack.pop()
        set_list[j].add(v)
        valid[v] = 1
        for i in g[v]:
          if valid[i] == -1:
            stack.append(i)
            set_list[j].add(i)
            valid[i] = 1
  ans = 1
  for i in range(len(set_list)):
    ans = max(len(set_list[i]),ans)

  print(ans)

else:
  print(1)

Solution (Python):
class UnionFind:
    def __init__(self,N):
        self.par=[i for i in range(N)]
        self.siz=[1 for _ in range(N)]
        self.rank=[0 for _ in range(N)]
    def find(self,x):
        if self.par[x]==x:
            return x
        else:
            self.par[x]=self.find(self.par[x])
            return self.par[x]
    def union(self,a,b):
        a=self.find(a)
        b=self.find(b)
        if a==b:
            return 0
        else:
            if self.rank[a]>self.rank[b]:
                self.par[b]=a
                self.siz[a]+=self.siz[b]
            else:
                self.par[a]=b
                self.siz[b]+=self.siz[a]
                if self.rank[a]==self.rank[b]:
                    self.rank[b]+=1
    def size(self,a):
        return self.siz[self.find(a)]
    def same(self,a,b):
        return self.find(a)==self.find(b)

N,M=map(int,input().split())
UF=UnionFind(N)
for i in range(M):
    A,B=map(lambda x:int(x)-1,input().split())
    UF.union(A,B)
ans=1
for i in range(N):
    ans=max(ans,UF.size(i))
print(ans)

Solution (Python):
import numpy as np

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


par = [i for i in range(N+1)]
size = [1 for _ in range(N+1)]

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

for AB in ABs:
    unite(AB[0],AB[1])

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

print(abs(min(uf.parents)))

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

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

if m != 0:
    edge = np.array([input().split() for _ in range(m)], dtype = np.int64).T
    tmp = np.ones(m, dtype = np.int64).T
    graph = csr_matrix((tmp, (edge[:] -1)), (n, n))

    cnt = collections.Counter(connected_components(graph)[1])

    print(max(cnt.values()))
else:
    print('1')