CodeEff/ECCO huggingface dataset:
# Original solution
n,m = list(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]

uf = UnionFind(n)

for i in range(m):
    a,b = list(map(int, input().split()))
    a -=1
    b -=1
    uf.union(a,b)
    
res = 0
for j in  uf.roots():
    res = max(res,len(uf.members(j)))
print(res)

# Optimized solution
n,m = list(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 roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

uf = UnionFind(n)

for i in range(m):
    a,b = list(map(int, input().split()))
    a -=1
    b -=1
    uf.union(a,b)
    
res = [0]
for j in  uf.roots():
    res.append(uf.size(j))
print((max(res)))
# Original solution
import collections

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

l = []
for _ in range(n):
  l.append([False] * n)

for x in range(n):
  l[x][x] = True

for a, b in ab:
  a -= 1
  b -= 1
  l[a][b] = True
  l[b][a] = True

c = [None] * n

for i in range(n):
  if c[i] is None:
    c[i] = i
  for j in range(n):
    if l[i][j]:
      if c[j] is None:
        c[j] = i

vs = []
for k, v in list(collections.Counter(c).items()):
  vs.append(v)

print((max(vs)))


# Optimized solution
import collections
import sys

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

l = []
for _ in range(n):
  l.append([])

# for x in range(n):
#   l[x]

for a, b in ab:
  a -= 1
  b -= 1
  l[a].append(b)
  l[b].append(a)

# c = [None] * n

# for i in range(n):
#   if c[i] is None:
#     c[i] = i
#   for f in l[i]:
#     if c[f] is None:
#       c[f] = i


# https://algo-logic.info/connected-components-num/

color = [None] * n

sys.setrecursionlimit(3*10**5)


def dfs(i, c):
  if color[i] is not None:
    return
  color[i] = c

  for f in l[i]:
    dfs(f, c)


for i in range(n):
  if color[i] is None:
    dfs(i, i)

print((max([v for k, v in list(collections.Counter(color).items())])))
# Original solution
from collections import deque

N, M = list(map(int, input().split()))
g = {i:set() for i in range(N)}
v = [-1 for i in range(N)]
for _ in range(M):
  a, b = list(map(int, input().split()))
  a, b = a-1, b-1
  g[a].add(b)
  g[b].add(a)

Q = deque()
ans = 0
for a in g:
  if v[a]==-1:
    v[a] = 1
    ans_tmp = 1
    Q.append(a)
    while len(Q)>0:
      na = Q.popleft()
      for nb in g[na]:
        if v[nb] == -1:
          v[nb] = 1
          ans_tmp += 1
          Q.append(nb)
    ans = max(ans, ans_tmp)
print(ans)


# Optimized solution
from collections import deque

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

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

checked = [False] * N
ans = 0

for i in range(N):
    if checked[i] == False:
        checked[i] = True
        DQ = deque(friends[i])
        tmp = 1
        while DQ:
            f = DQ.popleft()
            if checked[f] == False:
               checked[f] = True
               tmp += 1
               for j in friends[f]:
                   DQ.append(j)
        ans = max(ans, tmp)

print(ans)
# Original solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

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

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

        if x == y:
            return

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

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

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

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

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

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

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

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

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


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

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

ans = 0

for group in uf.roots():
    ans = max(ans, len(uf.members(group)))

print(ans)

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

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

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

        if x == y:
            return

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

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

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

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

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

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

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

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

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


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

uf = UnionFind(N)
for i in range(M):
    a, b = list(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)
# Original solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

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

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

        if x == y:
            return

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

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

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

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

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

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

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

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

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


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

    for _ in range(m):
        a, b = list(map(int, input().split()))
        uf.union(a-1, b-1)
    
    print((len(max(list(uf.all_group_members().values()), key=lambda x: len(x)))))


if __name__ == '__main__':
    main()

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

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

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

        if x == y:
            return

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

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

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

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

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

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

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

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

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


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

    for _ in range(m):
        a, b = list(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)


if __name__ == '__main__':
    main()
# Original solution
from collections import Counter
import sys

sys.setrecursionlimit(20000)


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


class UnionFind:
    def __init__(self, n: int) -> None:
        self._par = [i for i in range(n)]
        self._rank = [0] * n

    def root(self, n: int) -> int:
        p = self._par[n]
        if p == n:
            return p
        else:
            # compress
            self._par[n] = self.root(p)
            return self._par[n]

    def same(self, n: int, m: int) -> bool:
        return self.root(n) == self.root(m)

    def unite(self, n: int, m: int) -> None:
        pn = self.root(n)
        pm = self.root(m)
        if pn == pm:
            return
        self._par[pm] = pn


def main():
    n, m = _ia()
    uf = UnionFind(n)
    for _ in range(m):
        a, b = [x-1 for x in _ia()]
        uf.unite(a, b)
    c = Counter([uf.root(i) for i in range(n)])
    return max(c.values())


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


# Optimized solution
from collections import Counter
import sys


def _ia(): return list(map(int, sys.stdin.readline().strip().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 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)]

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

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

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

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

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

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


def main():
    n, m = _ia()
    uf = UnionFind(n)
    for _ in range(m):
        a, b = [x-1 for x in _ia()]
        uf.unite(a, b)
    return max(len(uf.members(r)) for r in uf.roots())


if __name__ == "__main__":
    print((main()))
# Original solution
from collections import Counter
import sys


def _ia(): return list(map(int, sys.stdin.readline().strip().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 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)]

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

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

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

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

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

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


def main():
    n, m = _ia()
    uf = UnionFind(n)
    for _ in range(m):
        a, b = [x-1 for x in _ia()]
        uf.unite(a, b)
    return max(len(uf.members(r)) for r in uf.roots())


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


# Optimized solution
from collections import Counter
import sys

sys.setrecursionlimit(20000)


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


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

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

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return
        elif self._rnk[x] > self._rnk[y]:
            self._par[x] += self._par[y]
            self._par[y] = x
        else:
            self._par[y] += self._par[x]
            self._par[x] = y
            if self._rnk[x] == self._rnk[y]:
                self._rnk[y] += 1

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


def main():
    n, m = _ia()
    uf = UnionFind(n)
    for _ in range(m):
        a, b = [x-1 for x in _ia()]
        uf.unite(a, b)
    c = Counter([uf.root(i) for i in range(n)])
    return max(c.values())


if __name__ == "__main__":
    print((main()))
# Original solution
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 {root: self.members(root) for root in self.roots()}

    def __str__(self):
        return '\n'.join(f'{root}: {self.members(root)}' for root in self.roots())


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

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

print((max(len(members) for members in list(uf.all_group_members().values()))))


# Optimized solution
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 {root: self.members(root) for root in self.roots()}

    def __str__(self):
        return '\n'.join(f'{root}: {self.members(root)}' for root in self.roots())


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

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

print((max(uf.size(i) for i in range(N))))
# Original solution
import sys
input=sys.stdin.readline
sys.setrecursionlimit(10 ** 6)
from itertools import accumulate
from itertools import permutations
from itertools import combinations
from collections import defaultdict
from collections import Counter
import fractions
import math
from collections import deque
from bisect import bisect_left
from bisect import bisect_right
from bisect import insort_left
import itertools
from heapq import heapify
from heapq import heappop
from heapq import heappush
import heapq
from copy import deepcopy
from decimal import Decimal
alf = list("abcdefghijklmnopqrstuvwxyz")
ALF = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
#import numpy as np
INF = float("inf")
#d = defaultdict(int)
#d = defaultdict(list)
N,M = list(map(int,input().split()))
count = [[0]*N for _ in range(N)]
fr = [[] for _ in range(N)]
for _ in range(M):
    a,b = list(map(int,input().split()))
    a,b = a-1,b-1
    if count[a][b] == 1:
        continue
    count[a][b] = 1
    count[b][a] = 1
    fr[a].append(b)
    fr[b].append(a)
used = [-1]*N 
MAX = 0
def dfs(fr,cur,parent):
    global cnt
    children = fr[cur]
    for chi in children:
        if used[chi] != -1:
            continue
        if chi == parent:
            continue
        used[chi] = 0
        cnt += 1
        dfs(fr,chi,cur)
    return

for i in range(N):
    cnt = 1
    if used[i] != -1:
        continue
    used[i] = 0
    dfs(fr,i,-1)
    MAX = max(MAX, cnt)
print(MAX)

            








# Optimized solution
import sys
input=sys.stdin.readline
sys.setrecursionlimit(10 ** 6)
from itertools import accumulate
from itertools import permutations
from itertools import combinations
from collections import defaultdict
from collections import Counter
import fractions
import math
from collections import deque
from bisect import bisect_left
from bisect import bisect_right
from bisect import insort_left
import itertools
from heapq import heapify
from heapq import heappop
from heapq import heappush
import heapq
from copy import deepcopy
from decimal import Decimal
alf = list("abcdefghijklmnopqrstuvwxyz")
ALF = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
#import numpy as np
INF = float("inf")
#d = defaultdict(int)
#d = defaultdict(list)
N,M = list(map(int,input().split()))
fr = [[] for _ in range(N)]
for _ in range(M):
    a,b = list(map(int,input().split()))
    a,b = a-1,b-1
    fr[a].append(b)
    fr[b].append(a)
used = [-1]*N 
MAX = 0
def dfs(fr,cur,parent):
    global cnt
    children = fr[cur]
    for chi in children:
        if used[chi] != -1:
            continue
        if chi == parent:
            continue
        used[chi] = 0
        cnt += 1
        dfs(fr,chi,cur)
    return

for i in range(N):
    cnt = 1
    if used[i] != -1:
        continue
    used[i] = 0
    dfs(fr,i,-1)
    MAX = max(MAX, cnt)
print(MAX)
# Original solution
import sys


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

    def _root(self, x):
        stack = []
        tbl = self.table
        while tbl[x] >= 0:
            stack.append(x)
            x = tbl[x]
        for y in stack:
            tbl[y] = x
        return x

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

    def union(self, x, y):
        r1 = self._root(x)
        r2 = self._root(y)
        if r1 == r2:
            return
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            self.table[r1] += d2
        else:
            self.table[r1] = r2
            self.table[r2] += d1


n, m = list(map(int, sys.stdin.buffer.readline().split()))
uf = UnionFind(n)
for x in sys.stdin.buffer.readlines():
    a, b = list(map(int, x.split()))
    uf.union(a-1, b-1)

grp = {}
for i in range(n):
    grp.setdefault(uf._root(i), []).append(i)

ans = 0
for x in list(grp.values()):
    l = len(x)
    if ans < l:
        ans = l
print(ans)


# Optimized solution
import sys


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

    def _root(self, x):
        stack = []
        tbl = self.table
        while tbl[x] >= 0:
            stack.append(x)
            x = tbl[x]
        for y in stack:
            tbl[y] = x
        return x

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

    def union(self, x, y):
        r1 = self._root(x)
        r2 = self._root(y)
        if r1 == r2:
            return
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            self.table[r1] += d2
        else:
            self.table[r1] = r2
            self.table[r2] += d1


def main():
    n, m = list(map(int, sys.stdin.buffer.readline().split()))
    uf = UnionFind(n)
    for x in sys.stdin.buffer.readlines():
        a, b = list(map(int, x.split()))
        uf.union(a-1, b-1)

    grp = {}
    for i in range(n):
        grp.setdefault(uf._root(i), []).append(i)

    ans = 0
    for x in list(grp.values()):
        l = len(x)
        if ans < l:
            ans = l
    print(ans)


if __name__ == "__main__":
    main()