CodeEff/ECCO huggingface dataset:
# Original solution
class uinon_find():
    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 = uinon_find(n)
for i in range(m):
    a,b = list(map(int,input().split()))
    a-=1
    b-=1
    uf.union(a,b)
#print(uf.all_group_members())
d = uf.all_group_members()
ans=0
for i in d:
    ans = max(len(d[i]),ans)
print(ans)

# Optimized solution
class uinon_find():
    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 = uinon_find(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.root=[-1]*n
        self.rank=[-1]*n

    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.rank[x]>self.rank[y]:
            self.root[x] +=self.root[y]
            self.root[y]=x
        else:
            self.root[y] +=self.root[x]
            self.root[x]=y
            if self.rank[x]==self.rank[y]:
                self.rank[y] +=1

    def isSameGroup(self,x,y):
        return self.Find_Root(x)==self.Find_Root(y)

    def size(self,x):
        return -self.root[self.Find_Root(x)]

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

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

    def group_members(self):
        return {i:self.members(i) for i in self.roots()}

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


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

UnionFind=UnionFind(n+1)
for a,b in AB:
    UnionFind.Unite(a,b)

A=UnionFind.group_members()
ans=0
for i in range(1,n+1):
    ans=max(ans,UnionFind.size(i))
print(ans)

# Optimized solution
import sys
input=sys.stdin.readline


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

    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.rank[x]>self.rank[y]:
            self.root[x] +=self.root[y]
            self.root[y]=x
        else:
            self.root[y] +=self.root[x]
            self.root[x]=y
            if self.rank[x]==self.rank[y]:
                self.rank[y] +=1

    def isSameGroup(self,x,y):
        return self.Find_Root(x)==self.Find_Root(y)

    def size(self,x):
        return -self.root[self.Find_Root(x)]

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

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

    def group_members(self):
        return {i:self.members(i) for i in self.roots()}

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


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

UnionFind=UnionFind(n+1)
for a,b in AB:
    if UnionFind.isSameGroup(a,b) is False:
        UnionFind.Unite(a,b)

ans=0
for i in range(1,n+1):
    cnt=UnionFind.size(i)
    if ans<cnt:
        ans=cnt
print(ans)
# Original solution
class UnionFindTree():
    def __init__(self, n):
        self.parents = list(range(n))
        self.rank = [0] * n

    def find(self, x):
        if self.parents[x] == x:
            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.rank[x] < self.rank[y]:
            self.parents[x] = y
        else:
            self.parents[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
  
N, M = list(map(int, input().split()))
uft = UnionFindTree(N)
for m in range(M):
  a, b = [int(x)-1 for x in input().split()]
  uft.union(a, b)
  
size = [uft.parents.count(n) for n in range(N)]
print((max(size)))

# Optimized solution
class UnionFindTree():
    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
        
        # 常にxの要素数＞yの要素数とする
        if self.parents[x] > self.parents[y]:
            x, y = y, x
            
        # self.parents[x] に　yの要素数を追加してから併合
        self.parents[x] += self.parents[y]
        self.parents[y] = x
  
N, M = list(map(int, input().split()))
uft = UnionFindTree(N)
for m in range(M):
  a, b = [int(x)-1 for x in input().split()]
  uft.union(a, b)
  
print((-min(uft.parents)))
# Original solution
#Union Find
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * (n+1)

    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 roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

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


N,M = list(map(int, input().split()))
uf = UnionFind(N)
for M in range(M):
  A,B = list(map(int, input().split()))
  uf.union(A,B)

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

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

  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())
  
N,M = list(map(int,input().split()))
UF = UnionFind(N)
for i in range(M):
  x, y = list(map(int, input().split()))
  UF.union(x,y)

ans = 0
for i in UF.roots():
  ans = max(ans, UF.size(i))
print(ans)
# Original solution
from collections import deque


N, M = list(map(int,input().split()))
mymap = [ [] for n in range(N) ]
for m in range(M):
    a, b = list(map(int, input().split()))
    mymap[a-1].append(b-1)
    mymap[b-1].append(a-1)
#print(mymap)
myans = 0
for n in range(N):
    mylist = mymap[n]
    #print(mylist)
    myd = deque()
    for mm in mylist:
        myd.append(mm)
    #print(myd)
    check_list = [0 for n in range(N)]
    mycnt = 1
    check_list[n] = 1
    while myd:
        tgt = myd.popleft()
        #print(tgt)
        if check_list[tgt] == 0 :
            for e in mymap[tgt]:
                if e > n :
                    myd.append(e)
            mycnt += 1
            check_list[tgt] = 1
    if myans < mycnt:
        myans = mycnt
print(myans)

# Optimized solution
from collections import deque


N, M = list(map(int,input().split()))
mymap = [ [] for n in range(N) ]
for m in range(M):
    a, b = list(map(int, input().split()))
    mymap[a-1].append(b-1)
    mymap[b-1].append(a-1)
#print(mymap)
myans = 0
check_list = [0 for n in range(N)]

for n in range(N):
    mylist = mymap[n]
    #print(mylist)
    myd = deque()
    for mm in mylist:
        myd.append(mm)
    #print(myd)
    mycnt = 1
    check_list[n] = 1
    while myd:
        tgt = myd.popleft()
        #print(tgt)
        if check_list[tgt] == 0 :
            for e in mymap[tgt]:
                if e > n :
                    myd.append(e)
            mycnt += 1
            check_list[tgt] = 1
    if myans < mycnt:
        myans = mycnt
print(myans)
# 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=[int(i) for i in input().split(" ")]
uf = UnionFind(N)
for i in range(M):
    A,B=[int(i) for i in input().split(" ")]
    uf.union(A-1,B-1)

print((max([len(i) for i in list(uf.all_group_members().values())])))


# Optimized solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1 for i 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 = 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=[int(i) for i in input().split(" ")]
uf = UnionFind(N)
for i in range(M):
    A,B=[int(i) for i in input().split(" ")]
    uf.union(A-1,B-1)

d={}
for i in range(N):
    root = uf.find(i)
    d[root]=d.get(root,0)+1

print((max(d.values())))
# Original solution
#xの根を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x])
        return par[x]
#xとyの属する集合の併合
def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        #sizeの大きいほうがx
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True

#xとyが同じ集合に属するかの判定
def same(x,y):
    return find(x) == find(y)

#xが属する集合の個数
def size(x):
    return -par[find(x)]

n, m = list(map(int,input().split()))
#初期化
#根なら-size,子なら親の頂点
par = [-1]*n

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

  
              

# Optimized solution
# データ構造: Union Find (素集合データ構造)
#  前提
#    グラフ（頂点と辺からなる集合）上の各頂点が、どの連結成分に属しているかを管理するときに使う
#    具体的には、各連結成分ごとに適当な1点を親として、同じ連結成分に属する他の点が子になるように配置する
#  できること
#    1, ある頂点の親を返す (つまり、どの連結成分に属するかがわかる)
#    2, 新たな辺が与えられた時、必要なら連結成分の統合を行う

# 以下、事前準備。(本処理は42行目から)
# 上記1,2を実現する関数を作成する。

# 0, 前提
# par = [-1 for _ in range(n)]
#  配列parの要素par[i]には、
#    頂点iが子の場合に 親頂点の番号
#    頂点iが親の場合に 属する連結成分の頂点数を格納する。(区別のため負数として表記)
#  例: par = [2, 2, -3, -1, 5, -1]
#    点0,1,2からなる連結成分、点3からなる連結成分、点4,5からなる連結成分がある場合。

# 1, 頂点xの親を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x])
        return par[x]
      
# 2, 頂点xとyが属する連結成分を結合する
def unite(x,y):
    x = find(x)
    y = find(y) 
    if x == y:
        return False
    else:
        #sizeの大きいほうがx
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True

# 以下、本処理
# 求めるもの：各連結成分の頂点数のうち、最大のもの
n, m = list(map(int,input().split()))
par = [-1 for _ in range(n)]
 
for _ in range(m): #各辺について
  a, b = list(map(int,input().split()))
  a -= 1
  b -= 1
  unite(a,b) #辺の両端(頂点aとb)が統合される
  
print((-min(par)))
# 各連結成分の頂点数は、配列parの中に負数として記録されている。
# 連結成分の最大の頂点数を求めたければ、そのminをとって-1倍すればよい。
# Original solution
n,m = list(map(int, input().split()))
frnd = [set([i]) for i in range(n+1)]
mx = 1
for _ in range(m):
  f1,f2 = list(map(int, input().split()))
  if f2 in frnd[f1]: continue
  frnd[f1] |= frnd[f2]
  frnd[f2] |= frnd[f1]
  mx = max(mx,len(frnd[f1]))
  for i in frnd[f1]-set([f1,f2]):
    frnd[i] |= frnd[f1]
print(mx)

# Optimized solution
n,m = list(map(int, input().split()))
par = [0]*(n+1)
group = [1]*(n+1)
for i in range(1,n+1): par[i]=i
def root(x):
  if par[x]==x: return x
  return root(par[x])

def union(x,y):
  rx = root(x)
  ry = root(y)
  if rx==ry: return
  par[max(rx,ry)] = min(rx,ry)
  group[min(rx,ry)] += group[max(rx,ry)]

for _ in range(m):
  f1,f2 = list(map(int, input().split()))
  union(f1,f2)
print((max(group)))
# 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 other_members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root and i != x]

    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 [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 = [int(x) - 1 for x in input().split()]
        uf.union(a, b)
    ans = 0
    for g in uf.all_group_members():
        ans = max(ans, len(g))
    print(ans)



if __name__ == '__main__':
    main()



# Optimized solution
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 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 main():
    input = sys.stdin.readline
    n, m = list(map(int, input().split()))
    uf = UnionFind(n)
    for _ in range(m):
        a, b = [int(x) - 1 for x in input().split()]
        uf.union(a, b)
    ans = max(-uf.parents[uf.find(x)] for x in uf.roots())
    print(ans)


if __name__ == '__main__':
    main()
# Original solution
def d_friends():
    class UnionFind(object):
        def __init__(self, n):
            """要素番号は 0 スタートを前提とする"""
            self.num_element = n
            self.parents = [-1] * n  # 要素が根の場合は、-(グループの要素数) を格納

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

        def union(self, x, y):
            """要素 x が属するグループと要素 y が属するグループとを併合する"""
            u, v = self.find(x), self.find(y)

            if u == v:
                return

            # u のグループの方が要素数が少なかった (parents の 定義より)
            if self.parents[u] > self.parents[v]:
                u, v = v, u

            self.parents[u] += self.parents[v]  # u と同グループの要素数を増やす
            self.parents[v] = u  # v は u に繋げる

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

        def get_roots(self):
            """根となっている要素のすべてを返す"""
            return [i for i, x in enumerate(self.parents) if x < 0]

    N, M = [int(i) for i in input().split()]
    uf = UnionFind(N)
    for _ in range(M):
        a, b = [int(i) - 1 for i in input().split()]
        uf.union(a, b)
    return max([len(uf.get_members(r)) for r in uf.get_roots()])

print((d_friends()))

# Optimized solution
def d_friends():
    class UnionFind(object):
        def __init__(self, n):
            """要素番号は 0 スタートを前提とする"""
            self.num_element = n
            self.parents = [-1] * n  # 要素が根の場合は、-(グループの要素数) を格納

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

        def union(self, x, y):
            """要素 x が属するグループと要素 y が属するグループとを併合する"""
            u, v = self.find(x), self.find(y)

            if u == v:
                return

            # u のグループの方が要素数が少なかった (parents の 定義より)
            if self.parents[u] > self.parents[v]:
                u, v = v, u

            self.parents[u] += self.parents[v]  # u と同グループの要素数を増やす
            self.parents[v] = u  # v は u に繋げる

        def get_size(self, x):
            """要素 x が属するグループの要素数を返す"""
            return -self.parents[self.find(x)]

    N, M = [int(i) for i in input().split()]
    uf = UnionFind(N)
    for _ in range(M):
        a, b = [int(i) - 1 for i in input().split()]
        uf.union(a, b)
    return max([uf.get_size(r) for r in range(N)])

print((d_friends()))